diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..332f3a5d3f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true + +# Set default charset +[*.{js,ts,scss,html}] +charset = utf-8 +indent_style = space +indent_size = 4 diff --git a/.gitignore b/.gitignore index 7b5df71f3c..ad57d28c1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,202 +1,14 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ - -# Visual Studo 2015 cache/options directory -.vs/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -*.[Cc]ache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ -bower_components/ -lib/ +.vs +.idea +.DS_Store +node_modules +npm-debug.log +vwd.webinfo css/ dist/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Other -src/js/*.min.js \ No newline at end of file +webfonts/ +*.pem +*.crx +*.zip +build/ +!dev-server.shared.pem diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..96c3cd3874 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "jslib"] + path = jslib + url = git@github.com:bitwarden/jslib.git + branch = master diff --git a/dev-server.shared.pem b/dev-server.shared.pem new file mode 100644 index 0000000000..908853556f --- /dev/null +++ b/dev-server.shared.pem @@ -0,0 +1,45 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaEy1cPw07irjg +4wUgaxshW7oQrgVoNZYRROmdU20K22L+HyG2ahW6usiWw8+6fPgVve7Y1z+/GYsK +DhaDdY1Ket3JvZHxoAJ/+6lYY+05PhtmYnyEZzZlnuYx/tu3vyGpsXqMpzL3ZrX2 +Mh2dWE7ZXKxsyig4wSDJhBPMrW8HKXLrLR/JPFhu/nz5MpRF5LfzWU13FEfmS43s +PEkBCn5ZxhVX4eNclQhTl7oOo5LU+KCWn+C/GPQir7pdmMoYF6D5j3qtbsq9irPe +qR7HsM9z6DnX+L0mF31P2S6OTgLT3kuWJn9vqLUwvQWGFvSSzpw7JgGBK3eX6zE9 +2koGWP9NAgMBAAECggEAIpwCie5TykxU1RQSfzegYaXuHLGRmB1RCMKYFOjlmGCD +EHOeZRXnBvCX3x2KfT1SHhk7q9xVeJ20LE9aEVj5qIVhZ6AXZnKPkwI8uRN61afe +r1wYCOdcgbo7LFoXQs0pqYXKPkJW217IqB8CBjO6p9KGZumago9cBb9ZaRVpVohZ +c6YHeatrna2mPb/EUPHdT0RHHQ5Dz2ToPjCkDtxsNHLZLekR35WIMtCBlp0xY5hb +5h54ZxnaMihvHTLa8L/pgxGEUsP+XFpdXkM1oREzh8tDRFcUL8mUVZq8bGyzALn5 +MxDhdXqxrnyD2cQ/cSqXLs1/2mh5eccU3g5IaNtrAQKBgQD0Q4K2UYXa8jWQu7jI +b37zwr2EypLFjeluqF4fxs+oz3UYEXeBDK0Td19/tze6/XieKibKDtFrOZQwDDKC +AVxD7Dm58T9Jf4LDHNYOfYL3X/E4H+JrVBh94s0B00jVJ6TnEQDMuLi+wMGtvTdW +huxoNefIWKf73ozvxIF+nsyeDQKBgQDkjYoXkBtfNgQR42RVA0/UdLLDWWctMU4F +sJYc1bLL3txbf+fK7QzbU/ggLMW0hv8/IdyirGJhW3G0K0yhpAOlPhe36qv4QyhD +o2nFlRrzfzvGJAgH9b1s+VcL/cSIuv4aCkbv97DAoQGPzAWEKv5gY1iw1DsGgrz5 +svZUvd7WQQKBgQDPrp7yuTngQNP+bT3dXb9JLqjIwRwt0E1LgugUiIuDcnCSuDct +iEOYK4UNKBDAckcd46T7Y8H3MwumFpjTJKj4L1+dk1tF+J6Lmnb99wVlozOLjsCK +lQQF9NJt3OEuKvjwZeqSJfUeavHB8QGeFjXnHP4nwAmEA2M9cYzQxeAf+QKBgCbS +U+6Er+GQT0iqk1RNZ7XyzJqaCQiII3Sb9iOXuPMgO9Xe+ARkF5b5wF/Wuw5bD+gt +XEjVdzCKU9oCsNWUAnqC/Yxj9CoLXj9+9mx1U0qhBgo1/Jc9ipuEDuEejc+b06Wg +sUP5krBlqNpAEX/Nvb+poFsI8a29b1QKrgTe64cBAoGALg92rZBG60N2n8fTokou +f1fui8Ftb+vOVGv9CM6icmNuwXeMF40A33Hvx14XLFk6B5p5dtVyOR660rRv4HRV +cBUm5wwCZjwR5Aj83XGR0PRbTNFNngHbawQiutSo6dw8cNNKCZMywVh2KX29dsLh +0Yj++kb8+G1kzFonR8WWoC8= +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIICwzCCAaugAwIBAgIJAN5sbMfEx05qMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMTCWxvY2FsaG9zdDAeFw0xODA2MDUwMzMxNDhaFw0yODA2MDIwMzMxNDhaMBQx +EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBANoTLVw/DTuKuODjBSBrGyFbuhCuBWg1lhFE6Z1TbQrbYv4fIbZqFbq6yJbD +z7p8+BW97tjXP78ZiwoOFoN1jUp63cm9kfGgAn/7qVhj7Tk+G2ZifIRnNmWe5jH+ +27e/IamxeoynMvdmtfYyHZ1YTtlcrGzKKDjBIMmEE8ytbwcpcustH8k8WG7+fPky +lEXkt/NZTXcUR+ZLjew8SQEKflnGFVfh41yVCFOXug6jktT4oJaf4L8Y9CKvul2Y +yhgXoPmPeq1uyr2Ks96pHsewz3PoOdf4vSYXfU/ZLo5OAtPeS5Ymf2+otTC9BYYW +9JLOnDsmAYErd5frMT3aSgZY/00CAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxo +b3N0MA0GCSqGSIb3DQEBCwUAA4IBAQCBTn7szrcs+fSs1Q/a2O3ng35zcme6NRhp +T65RP0ooj3tPT9QlTJyKjo9Yb2RW2RGVbQO86mkYe9N9wcZkzurZ6KDqsfBn3FkI +eZA1G/za907Dt/25mOdrsav7NmFBwxo9iuZ/cozgneK1mAXOu4nDI5yYvAlvNA6E +iXgls4WX1LtHL5b9YV7Jz27d5tTmGxEimakMBo+zr10vCtMCsTlDs/ChamnI7ljN +7B4WIVUMI3xOZzqClLnSzFJNReAlapjtGtp1qH6Y+6aZ9OErIwZOjE9CYYvm6MbE +CblXQ9Uifpwrc09TA5S2Y/9+VxUBF9xlxh8hkcGLTzlNFDzVWdmR +-----END CERTIFICATE----- diff --git a/dist/.publish b/dist/.publish deleted file mode 160000 index be3a93a581..0000000000 --- a/dist/.publish +++ /dev/null @@ -1 +0,0 @@ -Subproject commit be3a93a58193fb727b597657ef40aac9395b5f36 diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 070c5c0800..0000000000 --- a/gulpfile.js +++ /dev/null @@ -1,499 +0,0 @@ -/// - -var gulp = require('gulp'), - rimraf = require('rimraf'), - concat = require('gulp-concat'), - rename = require('gulp-rename'), - cssmin = require('gulp-cssmin'), - uglify = require('gulp-uglify'), - ghPages = require('gulp-gh-pages'), - less = require('gulp-less'), - connect = require('gulp-connect'), - ngAnnotate = require('gulp-ng-annotate'), - preprocess = require('gulp-preprocess'), - runSequence = require('run-sequence'), - jeditor = require("gulp-json-editor"), - merge = require('merge-stream'), - ngConfig = require('gulp-ng-config'), - settings = require('./settings.json'), - project = require('./package.json'), - jshint = require('gulp-jshint'), - _ = require('lodash'), - webpack = require('webpack-stream'), - browserify = require('browserify'), - derequire = require('gulp-derequire'), - source = require('vinyl-source-stream'); - -var paths = {}; -paths.dist = './dist/'; -paths.webroot = './src/'; -paths.js = paths.webroot + 'js/**/*.js'; -paths.minJs = paths.webroot + 'js/**/*.min.js'; -paths.concatJsDest = paths.webroot + 'js/bw.min.js'; -paths.libDir = paths.webroot + 'lib/'; -paths.npmDir = 'node_modules/'; -paths.lessDir = paths.webroot + 'less/'; -paths.cssDir = paths.webroot + 'css/'; -paths.jsDir = paths.webroot + 'js/'; - -var randomString = Math.random().toString(36).substring(7); - -gulp.task('lint', function () { - return gulp.src(paths.webroot + 'app/**/*.js') - .pipe(jshint()) - .pipe(jshint.reporter('default')); -}); - -gulp.task('build', function (cb) { - return runSequence( - 'clean', - ['browserify', 'lib', 'webpack', 'less', 'settings', 'lint', 'min:js'], - cb); -}); - -gulp.task('clean:js', function (cb) { - return rimraf(paths.concatJsDest, cb); -}); - -gulp.task('clean:css', function (cb) { - return rimraf(paths.cssDir, cb); -}); - -gulp.task('clean:lib', function (cb) { - return rimraf(paths.libDir, cb); -}); - -gulp.task('clean', ['clean:js', 'clean:css', 'clean:lib', 'dist:clean']); - -gulp.task('min:js', ['clean:js'], function () { - return gulp.src( - [ - paths.js, - '!' + paths.minJs, - '!' + paths.jsDir + 'fallback*.js', - '!' + paths.jsDir + 'u2f-connector.js', - '!' + paths.jsDir + 'duo-connector.js', - '!' + paths.jsDir + 'duo.js', - '!' + paths.jsDir + 'settings.js' - ], { base: '.' }) - .pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } })) - .pipe(concat(paths.concatJsDest)) - //.pipe(uglify()) - .pipe(gulp.dest('.')); -}); - -gulp.task('min:css', [], function () { - return gulp.src([paths.cssDir + '**/*.css', '!' + paths.cssDir + '**/*.min.css'], { base: '.' }) - .pipe(cssmin()) - .pipe(rename({ suffix: '.min' })) - .pipe(gulp.dest('.')); -}); - -gulp.task('min', ['min:js', 'min:css']); - -gulp.task('lib', ['clean:lib'], function () { - var libs = [ - { - src: [ - paths.npmDir + 'bootstrap/dist/**/*', - '!' + paths.npmDir + 'bootstrap/dist/**/npm.js', - '!' + paths.npmDir + 'bootstrap/dist/**/css/*theme*' - ], - dest: paths.libDir + 'bootstrap' - }, - { - src: paths.npmDir + 'font-awesome/css/*', - dest: paths.libDir + 'font-awesome/css' - }, - { - src: paths.npmDir + 'font-awesome/fonts/*', - dest: paths.libDir + 'font-awesome/fonts' - }, - { - src: paths.npmDir + 'jquery/dist/*.js', - dest: paths.libDir + 'jquery' - }, - { - src: paths.npmDir + 'admin-lte/dist/js/app*.js', - dest: paths.libDir + 'admin-lte/js' - }, - { - src: paths.npmDir + 'angular/angular*.js', - dest: paths.libDir + 'angular' - }, - { - src: paths.npmDir + 'angular-ui-bootstrap/dist/*tpls*.js', - dest: paths.libDir + 'angular-ui-bootstrap' - }, - { - src: paths.npmDir + 'angular-bootstrap-show-errors/src/*.js', - dest: paths.libDir + 'angular-bootstrap-show-errors' - }, - { - src: paths.npmDir + 'angular-cookies/*cookies*.js', - dest: paths.libDir + 'angular-cookies' - }, - { - src: paths.npmDir + 'angular-jwt/dist/*.js', - dest: paths.libDir + 'angular-jwt' - }, - { - src: paths.npmDir + 'angular-resource/*resource*.js', - dest: paths.libDir + 'angular-resource' - }, - { - src: paths.npmDir + 'angular-sanitize/*sanitize*.js', - dest: paths.libDir + 'angular-sanitize' - }, - { - src: [paths.npmDir + 'angular-toastr/dist/**/*.css', paths.npmDir + 'angular-toastr/dist/**/*.js'], - dest: paths.libDir + 'angular-toastr' - }, - { - src: paths.npmDir + 'angular-ui-router/release/*.js', - dest: paths.libDir + 'angular-ui-router' - }, - { - src: paths.npmDir + 'angular-messages/*messages*.js', - dest: paths.libDir + 'angular-messages' - }, - { - src: paths.npmDir + 'ngstorage/*.js', - dest: paths.libDir + 'ngstorage' - }, - { - src: paths.npmDir + 'papaparse/papaparse*.js', - dest: paths.libDir + 'papaparse' - }, - { - src: paths.npmDir + 'ngclipboard/dist/ngclipboard*.js', - dest: paths.libDir + 'ngclipboard' - }, - { - src: paths.npmDir + 'clipboard/dist/clipboard*.js', - dest: paths.libDir + 'clipboard' - }, - { - src: paths.npmDir + 'node-forge/dist/prime.worker.*', - dest: paths.libDir + 'forge' - }, - { - src: [ - paths.npmDir + 'angulartics-google-analytics/lib/angulartics*.js', - paths.npmDir + 'angulartics/src/angulartics.js' - ], - dest: paths.libDir + 'angulartics' - }, - //{ - // src: paths.npmDir + 'duo_web_sdk/index.js', - // dest: paths.libDir + 'duo' - //}, - { - src: paths.jsDir + 'duo.js', - dest: paths.libDir + 'duo' - }, - { - src: paths.npmDir + 'angular-promise-polyfill/index.js', - dest: paths.libDir + 'angular-promise-polyfill' - } - ]; - - var tasks = libs.map(function (lib) { - return gulp.src(lib.src).pipe(gulp.dest(lib.dest)); - }); - - return merge(tasks); -}); - -gulp.task('webpack', ['webpack:forge']); - -gulp.task('webpack:forge', function () { - var forgeDir = paths.npmDir + '/node-forge/lib/'; - - return gulp.src([ - forgeDir + 'pbkdf2.js', - forgeDir + 'aes.js', - forgeDir + 'rsa.js', - forgeDir + 'hmac.js', - forgeDir + 'sha256.js', - forgeDir + 'random.js', - forgeDir + 'forge.js' - ]).pipe(webpack({ - output: { - filename: 'forge.js', - library: 'forge', - libraryTarget: 'umd' - }, - node: { - Buffer: false, - process: false, - crypto: false, - setImmediate: false - } - })).pipe(gulp.dest(paths.libDir + 'forge')); -}); - -gulp.task('settings', function () { - return config() - .pipe(gulp.dest(paths.webroot + 'app')); -}); - -function config() { - return gulp.src('./settings.json') - .pipe(ngConfig('bit', { - createModule: false, - constants: _.merge({}, { - appSettings: { - selfHosted: false, - version: project.version, - environment: project.env - } - }, require('./settings' + (project.env !== 'Development' ? ('.' + project.env) : '') + '.json') || {}) - })); -} - -gulp.task('less', function () { - return gulp.src(paths.lessDir + 'vault.less') - .pipe(less()) - .pipe(gulp.dest(paths.cssDir)); -}); - -gulp.task('watch', function () { - gulp.watch(paths.lessDir + '*.less', ['less']); - gulp.watch('./settings*.json', ['settings']); -}); - -gulp.task('browserify', ['browserify:stripe', 'browserify:cc']); - -gulp.task('browserify:stripe', function () { - return browserify(paths.npmDir + 'angular-stripe/src/index.js', - { - entry: '.', - standalone: 'angularStripe', - global: true - }) - .transform('exposify', { expose: { angular: 'angular' } }) - .bundle() - .pipe(source('angular-stripe.js')) - .pipe(derequire()) - .pipe(gulp.dest(paths.libDir + 'angular-stripe')); -}); - -gulp.task('browserify:cc', function () { - return browserify(paths.npmDir + 'angular-credit-cards/src/index.js', - { - entry: '.', - standalone: 'angularCreditCards' - }) - .transform('exposify', { expose: { angular: 'angular' } }) - .bundle() - .pipe(source('angular-credit-cards.js')) - .pipe(derequire()) - .pipe(gulp.dest(paths.libDir + 'angular-credit-cards')); -}); - -gulp.task('dist:clean', function (cb) { - return rimraf(paths.dist + '**/*', cb); -}); - -gulp.task('dist:move', function () { - var moves = [ - { - src: './CNAME', - dest: paths.dist - }, - { - src: [ - paths.npmDir + 'bootstrap/dist/**/bootstrap.min.js', - paths.npmDir + 'bootstrap/dist/**/bootstrap.min.css', - paths.npmDir + 'bootstrap/dist/**/fonts/**/*' - ], - dest: paths.dist + 'lib/bootstrap' - }, - { - src: [ - paths.npmDir + 'font-awesome/**/font-awesome.min.css', - paths.npmDir + 'font-awesome/**/fonts/**/*' - ], - dest: paths.dist + 'lib/font-awesome' - }, - { - src: paths.npmDir + 'jquery/dist/jquery.min.js', - dest: paths.dist + 'lib/jquery' - }, - { - src: paths.npmDir + 'angular/angular.min.js', - dest: paths.dist + 'lib/angular' - }, - { - src: paths.npmDir + 'node-forge/dist/prime.worker.*', - dest: paths.dist + 'lib/forge' - }, - //{ - // src: paths.npmDir + 'duo_web_sdk/index.js', - // dest: paths.dist + 'lib/duo' - //}, - { - src: paths.jsDir + 'duo.js', - dest: paths.dist + 'js' - }, - { - src: paths.jsDir + 'duo-connector.js', - dest: paths.dist + 'js' - }, - { - src: paths.jsDir + 'settings.js', - dest: paths.dist + 'js' - }, - { - src: paths.jsDir + 'bw.min.js', - dest: paths.dist + 'js' - }, - { - src: [ - paths.webroot + '**/app/**/*.html', - paths.webroot + '**/images/**/*', - paths.webroot + 'index.html', - paths.webroot + 'u2f-connector.html', - paths.webroot + 'duo-connector.html', - paths.webroot + 'favicon.ico', - paths.webroot + 'manifest.json', - paths.webroot + 'app-id.json' - ], - dest: paths.dist - } - ]; - - var tasks = moves.map(function (move) { - return gulp.src(move.src).pipe(gulp.dest(move.dest)); - }); - - return merge(tasks); -}); - -gulp.task('dist:css', function () { - return gulp - .src([ - paths.cssDir + '**/*.css', - '!' + paths.cssDir + '**/*.min.css' - ]) - .pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } })) - .pipe(cssmin()) - .pipe(rename({ suffix: '.min' })) - .pipe(gulp.dest(paths.dist + 'css')); -}); - -gulp.task('dist:js:app', function () { - var mainStream = gulp - .src([ - paths.webroot + 'app/app.js', - '!' + paths.webroot + 'app/settings.js', - paths.webroot + 'app/**/*Module.js', - paths.webroot + 'app/**/*.js' - ]); - - merge(mainStream, config()) - .pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } })) - .pipe(concat(paths.dist + '/js/app.min.js')) - .pipe(ngAnnotate()) - //.pipe(uglify()) - .pipe(gulp.dest('.')); -}); - -gulp.task('dist:js:fallback', function () { - var mainStream = gulp - .src([ - paths.jsDir + 'fallback*.js' - ]); - - merge(mainStream) - .pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } })) - //.pipe(uglify()) - .pipe(rename({ suffix: '.min' })) - .pipe(gulp.dest(paths.dist + 'js')); -}); - -gulp.task('dist:js:u2f', function () { - var mainStream = gulp - .src([ - paths.jsDir + 'u2f*.js' - ]); - - merge(mainStream) - .pipe(concat(paths.dist + '/js/u2f.min.js')) - //.pipe(uglify()) - .pipe(gulp.dest('.')); -}); - -gulp.task('dist:js:lib', function () { - return gulp - .src([ - paths.libDir + 'angulartics/angulartics.js', - paths.libDir + '**/*.js', - '!' + paths.libDir + '**/*.min.js', - '!' + paths.libDir + 'angular/**/*', - '!' + paths.libDir + 'bootstrap/**/*', - '!' + paths.libDir + 'jquery/**/*' - ]) - .pipe(concat(paths.dist + '/js/lib.min.js')) - //.pipe(uglify()) - .pipe(gulp.dest('.')); -}); - -gulp.task('dist:preprocess', function () { - return gulp - .src([ - paths.dist + '/**/*.html' - ], { base: '.' }) - .pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } })) - .pipe(gulp.dest('.')); -}); - -gulp.task('dist:version', function () { - gulp.src(paths.webroot + 'version.json').pipe(jeditor({ - 'version': project.version - })).pipe(gulp.dest(paths.dist)); -}); - -gulp.task('dist', ['build'], function (cb) { - return runSequence( - 'dist:clean', - ['dist:move', 'dist:css', 'dist:js:app', 'dist:js:lib', 'dist:js:fallback', 'dist:js:u2f', 'dist:version'], - 'dist:preprocess', - cb); -}); - -var selfHosted = false; -gulp.task('dist:selfHosted', function (cb) { - selfHosted = true; - return runSequence('dist', cb); -}); - -gulp.task('deploy', ['dist'], function () { - return gulp.src(paths.dist + '**/*') - .pipe(ghPages({ cacheDir: paths.dist + '.publish' })); -}); - -gulp.task('deploy-preview', ['dist'], function () { - return gulp.src(paths.dist + '**/*') - .pipe(ghPages({ - cacheDir: paths.dist + '.publish', - remoteUrl: 'git@github.com:bitwarden/web-preview.git' - })); -}); - -gulp.task('serve', function () { - connect.server({ - port: 4001, - root: ['src'], - //https: true, - middleware: function (connect, opt) { - return [function (req, res, next) { - if (req.originalUrl.indexOf('app-id.json') > -1) { - res.setHeader('Content-Type', 'application/fido.trusted-apps+json'); - } - next(); - }]; - } - }); -}); diff --git a/jslib b/jslib new file mode 160000 index 0000000000..89e71d7c16 --- /dev/null +++ b/jslib @@ -0,0 +1 @@ +Subproject commit 89e71d7c16d95fd7cc9634d46e0db1d77e6fcae6 diff --git a/package-lock.json b/package-lock.json index 7055487661..e88ac7464c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,570 @@ { - "name": "bitwarden", - "version": "1.27.0", + "name": "bitwarden-web", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { - "JSONStream": { - "version": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "@angular/animations": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.2.0.tgz", + "integrity": "sha512-JLR42YHiJppO4ruAkFxgbzghUDtHkXHkKPM8udd2qyt16T7e1OX7EEOrrmldUu59CC56tZnJ/32p4SrYmxyBSA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/common": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.2.0.tgz", + "integrity": "sha512-yMFn2isC7/XOs56/2Kzzbb1AASHiwipAPOVFtKe7TdZQClO8fJXwCnk326rzr615+CG0eSBNQWeiFGyWN2riBA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/compiler": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.2.0.tgz", + "integrity": "sha512-RfYa4ESgjGX0T0ob/Xz00IF7nd2xZkoyRy6oKgL82q42uzB3xZUDMrFNgeGxAUs3H22IkL46/5SSPOMOTMZ0NA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/compiler-cli": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.2.0.tgz", + "integrity": "sha512-+Kef4NjuHwLj2hRPdVo4yAtPmv+kn0Nu/ShmKfaEK4mt9aaQMFxKNt6beUuDK5iUPMB5nuTCZ4bqEFpqd+EtxQ==", "dev": true, "requires": { - "jsonparse": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + "chokidar": "1.7.0", + "minimist": "1.2.0", + "reflect-metadata": "0.1.12", + "tsickle": "0.26.0" + } + }, + "@angular/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.2.0.tgz", + "integrity": "sha512-s2ne45DguNUubhC1YgybGECC4Tyx3G4EZCntUiRMDWWkmKXSK+6dgHMesyDo8R5Oat8VfN4Anf8l3JHS1He8kg==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/forms": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.2.0.tgz", + "integrity": "sha512-g1/SF9lY0ZwzJ0w4NXbFsTGGEuUdgtaZny8DmkaqtmA7idby3FW398X0tv25KQfVYKtL+p9Jp1Y8EI0CvrIsvw==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/http": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.2.0.tgz", + "integrity": "sha512-V5Cl24dP3rCXTTQvDc0TIKoWqBRAa0DWAQbtr7iuDAt5a1vPGdKz5K1sEiiV6ziwX6gzjiwHjUvL+B+WbIUrQA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/platform-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.2.0.tgz", + "integrity": "sha512-c6cR15MfopPwGZ097HdRuAi9+R9BhA3bRRFpP2HmrSSB/BW4ZNovUYwB2QUMSYbd9s0lYTtnavqGm6DKcyF2QA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/platform-browser-dynamic": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.2.0.tgz", + "integrity": "sha512-xG1eNoi8sm4Jcly2y98r5mqYVe3XV8sUJCtOhvGBYtvt4dKEQ5tOns6fWQ0nUbl6Vv3Y0xgGUS1JCtfut3DuaQ==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.2.0.tgz", + "integrity": "sha512-VXDXtp2A1GQEUEhXg0ZzqHdTUERLgDSo3/Mmpzt+dgLMKlXDSCykcm4gINwE5VQLGD1zQvDFCCRv3seGRNfrqA==", + "requires": { + "tslib": "1.9.2" + } + }, + "@angular/upgrade": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@angular/upgrade/-/upgrade-5.2.0.tgz", + "integrity": "sha512-ezWfhBCiP7RX+59scxfYfjDMRw+qq0BVbm/EfOXdYFU0NHWo7lXJ3v+cUi18G+5GVjzwRiJDIKWhw1QEyq2nug==", + "requires": { + "tslib": "1.9.2" + } + }, + "@ngtools/webpack": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz", + "integrity": "sha512-3u2zg2rarG3qNLSukBClGADWuq/iNn5SQtlSeAbfKzwBeyLGbF0gN1z1tVx1Bcr8YwFzR6NdRePQmJGcoqq1fg==", + "dev": true, + "requires": { + "chalk": "2.2.2", + "enhanced-resolve": "3.4.1", + "loader-utils": "1.1.0", + "magic-string": "0.22.5", + "semver": "5.5.0", + "source-map": "0.5.7", + "tree-kill": "1.2.0", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.2.tgz", + "integrity": "sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "@shellscape/koa-send": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@shellscape/koa-send/-/koa-send-4.1.3.tgz", + "integrity": "sha512-akNxJetq2ak8aj7U6ys+EYXfWY4k8keleDZJbHWvpuVDj0/PUbbOuPkeBYaie7C6d5fRNLK+0M1Puu8ywTlj3w==", + "dev": true, + "requires": { + "debug": "2.6.9", + "http-errors": "1.6.3", + "mz": "2.7.0", + "resolve-path": "1.4.0" + } + }, + "@shellscape/koa-static": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@shellscape/koa-static/-/koa-static-4.0.5.tgz", + "integrity": "sha512-0T2g2NtaO2zhbqR8EBACIGtBy+haodKb8PuJ17RGDXAJwhjkgghUKLrLEnm05zuiwupfYm2APIax6D2TwLoflA==", + "dev": true, + "requires": { + "@shellscape/koa-send": "4.1.3", + "debug": "2.6.9" + } + }, + "@types/jquery": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.2.tgz", + "integrity": "sha512-ByZwKSEqteAta4VrIalqGJZmMq9lWPD3H3f5Xs6RR8B7zQRDPGUtjoKBYNtKTz/7LgBEQMdlxVbbjQfUaEIItA==", + "dev": true + }, + "@types/lunr": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.1.5.tgz", + "integrity": "sha512-esk3CG25hRtHsVHm+LOjiSFYdw8be3uIY653WUwR43Bro914HSimPgPpqgajkhTJ0awK3RQfaIxP7zvbtCpcyg==", + "dev": true + }, + "@types/node": { + "version": "8.0.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.19.tgz", + "integrity": "sha512-VRQB+Q0L3YZWs45uRdpN9oWr82meL/8TrJ6faoKT5tp0uub2l/aRMhtm5fo68h7kjYKH60f9/bay1nF7ZpTW5g==", + "dev": true + }, + "@types/node-forge": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-0.6.10.tgz", + "integrity": "sha512-O66D2B9OZDP+vTvfDJUJnk/HfOueeerLXNZQtVY+1ICbp6hO0ySkOtt+N+MGa24YS48JzavN6C2BjYBnKTGwiw==", + "dev": true + }, + "@types/papaparse": { + "version": "4.1.33", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-4.1.33.tgz", + "integrity": "sha512-FYId1z6LvtfJD5nz7ThbOxkSuuQl63RJ5w3W1UFlFoycMfCdCXxvqWG+EQrN23HiiJftai7JAlxgmuplkVyoCQ==", + "dev": true + }, + "@types/webcrypto": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/webcrypto/-/webcrypto-0.0.28.tgz", + "integrity": "sha512-jzAoSUvqA+183nJO/Sc73CREQJsv+p77WJdn532GqA3YXQzlwRwHhClVa7U4O8iB2sJSR7G3v6f1mJFNkwA9YQ==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.9.tgz", + "integrity": "sha512-xL3hC0TOc4ic1UNG8ZZNeaiPf1klozt6rqajcy7hfO/qqfkEhLff1AFt5g2LJkTjhw+QSEYVMt7qOaaApu7JzA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.5.9", + "@webassemblyjs/helper-wasm-bytecode": "1.5.9", + "@webassemblyjs/wast-parser": "1.5.9", + "debug": "3.1.0", + "mamacro": "0.0.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.9.tgz", + "integrity": "sha512-naMJjuBqDqx4dPSzwpI9pkjdLds4tDTzvsOEzwxPDp655IfgLLP/QEvK/9PQp4p5DExqrR87rk8DWByoqWWlGA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.9.tgz", + "integrity": "sha512-tzGdqBo7Xf3McJcXbwbwzwElRzF/nELJN+G4MGGfm0DGRQB6UTmMe44jFIOQYT1Za89Aiz5DMQJotdnnLheixw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.9.tgz", + "integrity": "sha512-WYkys6y33viEY23tHJ+KkSd9yHZBd54Sy6gcSgwLGPP1or9pLqWBrjWWATHuDuIkpvSJSt/+3qjAV6zHd1nS0g==", + "dev": true, + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.9.tgz", + "integrity": "sha512-SYjNAlqcRH+YynslbIhFYOnGvE3WBl82/XlcFXiNkqnWsvHWnNkJbtxAtzrT/dcf69O/2pt8j1Q0+qc/rtacVw==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.5.9" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.9.tgz", + "integrity": "sha512-8D+VVIJTRbsn31zt3eyidYyUkhH1jk2/58mrIPiMarflRsisItJa5WZVu/gw0l+ubFOJf9PivTJB6Kw/Kgxx3g==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.9.tgz", + "integrity": "sha512-DbeLbFOhioEeY7yAff12+n5sf7WP7Fmi0lnhCSzfW4xBsgwXKmRjAx7nVmsUf3z+BDnwHHVKIXBUM+ucccNUsw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.9.tgz", + "integrity": "sha512-zHQuTMMd2nTyEa3fbmGfzlJW305py1sgf1gHNCO/LVN8nWlKysB/+6J68sP1Cd+9USnT1VS2vyD1z+YJPS6GqQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.9.tgz", + "integrity": "sha512-+ff+8Ju6sLCMFNygcDdLRNRsmuD0PHwq77d2mbfWj5YzUvFaKN2q2kRppJSEAixOnM2xLADuG5y/blpMo5G90A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/helper-buffer": "1.5.9", + "@webassemblyjs/helper-wasm-bytecode": "1.5.9", + "@webassemblyjs/wasm-gen": "1.5.9", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/ieee754": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.5.9.tgz", + "integrity": "sha512-mhetZBDnpV3VYqZb5Aail9X01VyIqDDZrNYdYj8bfx/PsVPG2znX90wRyVNTeqC5ylqHCgGkJ63bPaPEyINfsw==", + "dev": true, + "requires": { + "ieee754": "1.1.11" + } + }, + "@webassemblyjs/leb128": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.5.9.tgz", + "integrity": "sha512-oZ3eUB9EViUtiuMwW/xeYamXgfFS2cmXl6aUIYBfpXJQ5v5aOC8ZuPpz2/LqlgNlT8ThpyFd6kfgkYVwKwkGvQ==", + "dev": true, + "requires": { + "leb": "0.3.0" + } + }, + "@webassemblyjs/wasm-edit": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.9.tgz", + "integrity": "sha512-pMWe3HomnWAMZytJ5sSNBS6qTbSoULUHkvDrtcarmLBTclmupZe25INy1jxbWGKsuFxw6w0xQ+eLRPlC8HPjhg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/helper-buffer": "1.5.9", + "@webassemblyjs/helper-wasm-bytecode": "1.5.9", + "@webassemblyjs/helper-wasm-section": "1.5.9", + "@webassemblyjs/wasm-gen": "1.5.9", + "@webassemblyjs/wasm-opt": "1.5.9", + "@webassemblyjs/wasm-parser": "1.5.9", + "@webassemblyjs/wast-printer": "1.5.9", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.9.tgz", + "integrity": "sha512-UEhymlxupBUJuwnD2N860MqkpE7LHt0tNKqAgT4YAVjbx+88P6MBBk+q+9wr2FJCXxMgsPTxMWifqC4wd2FzVg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/helper-wasm-bytecode": "1.5.9", + "@webassemblyjs/ieee754": "1.5.9", + "@webassemblyjs/leb128": "1.5.9" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.9.tgz", + "integrity": "sha512-oQm84US3e36dPq5bOeybVKA2ZyzeWR4fereg9kJa0Y9XLKxHwlsBa2kFyNXwZNrhMP33iyXAW+ym7om1zPZeAg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/helper-buffer": "1.5.9", + "@webassemblyjs/wasm-gen": "1.5.9", + "@webassemblyjs/wasm-parser": "1.5.9", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.9.tgz", + "integrity": "sha512-jBKBTKE4M/WYCSqLjRvK+/QD55E/HNcQjswbksof3GEXfkq0iMqYxoPfqR7uLAD9/jVf9HpBNW2FJOyfTTlYfw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/helper-api-error": "1.5.9", + "@webassemblyjs/helper-wasm-bytecode": "1.5.9", + "@webassemblyjs/ieee754": "1.5.9", + "@webassemblyjs/leb128": "1.5.9", + "@webassemblyjs/wasm-parser": "1.5.9" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.5.9.tgz", + "integrity": "sha512-bDuYH/NR5D+MmwVZdGW2rUvu4UcKGpodiHBSueajon3oNPu+PAKG+7br3BVFKxDUtDoVtuHLUQvkqp1lTrqPCA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/floating-point-hex-parser": "1.5.9", + "@webassemblyjs/helper-api-error": "1.5.9", + "@webassemblyjs/helper-code-frame": "1.5.9", + "@webassemblyjs/helper-fsm": "1.5.9", + "long": "3.2.0", + "mamacro": "0.0.3" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.5.9.tgz", + "integrity": "sha512-04iV32TO69kZChP3DN6W8i6GCa5UtEn1Lnzb4sQGe5YNjIFz2k8+KZLxbovWIZgj9pk06k3Egq/wyD98lSKaLw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/wast-parser": "1.5.9", + "long": "3.2.0" + } + }, + "@webpack-contrib/config-loader": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@webpack-contrib/config-loader/-/config-loader-1.1.3.tgz", + "integrity": "sha512-lOliuisjrh24MfhOYE5ljqyFlKfzyWGFrn3bbR0KlXQHY90j3pXWfFtEl4gNvqz69tJsM+1s7PUGJrK9CF46ng==", + "dev": true, + "requires": { + "@webpack-contrib/schema-utils": "1.0.0-beta.0", + "chalk": "2.4.1", + "cosmiconfig": "5.0.5", + "loud-rejection": "1.6.0", + "merge-options": "1.0.1", + "minimist": "1.2.0", + "resolve": "1.7.1", + "webpack-log": "1.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "@webpack-contrib/schema-utils": { + "version": "1.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz", + "integrity": "sha512-LonryJP+FxQQHsjGBi6W786TQB1Oym+agTpY0c+Kj8alnIw+DLUJb6SI8Y1GHGhLCH1yPRrucjObUmxNICQ1pg==", + "dev": true, + "requires": { + "ajv": "6.5.0", + "ajv-keywords": "3.2.0", + "chalk": "2.4.1", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "webpack-log": "1.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } } }, "abbrev": { @@ -20,714 +574,500 @@ "dev": true }, "accepts": { - "version": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" - } - }, - "accessory": { - "version": "https://registry.npmjs.org/accessory/-/accessory-1.1.0.tgz", - "integrity": "sha1-eDPpg5oy3tdtJgIfNqQXB6Ug9ZM=", - "dev": true, - "requires": { - "ap": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", - "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", - "dot-parts": "https://registry.npmjs.org/dot-parts/-/dot-parts-1.0.1.tgz" - }, - "dependencies": { - "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", - "integrity": "sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc=", - "dev": true - } - } - }, - "accord": { - "version": "https://registry.npmjs.org/accord/-/accord-0.27.3.tgz", - "integrity": "sha1-f7kSlwkoXK6oTrNyxOiCAxtxOOg=", - "dev": true, - "requires": { - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "indx": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", - "lodash.clone": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "lodash.defaults": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "lodash.flatten": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "lodash.merge": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", - "lodash.partialright": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", - "lodash.pick": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "lodash.uniq": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "when": "https://registry.npmjs.org/when/-/when-3.7.8.tgz" - }, - "dependencies": { - "convert-source-map": { - "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "dev": true, - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "lodash.defaults": { - "version": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=", - "dev": true - } + "mime-types": "2.1.18", + "negotiator": "0.6.1" } }, "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.1.tgz", + "integrity": "sha512-XH4o5BK5jmw9PzSGK7mNf+/xV+mPxQxGZoeC36OVsJZYV77JAG9NnI7T90hoUpI/C1TOfXWTvugRdZ9ZR3iE2Q==", "dev": true }, "acorn-dynamic-import": { - "version": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", "dev": true, "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" + "acorn": "5.6.1" } }, - "admin-lte": { - "version": "https://registry.npmjs.org/admin-lte/-/admin-lte-2.3.11.tgz", - "integrity": "sha1-2lbc001C6e8a82K+FVIKBTqdQ9s=", - "dev": true - }, "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", "dev": true, - "optional": true, "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" - }, - "dependencies": { - "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "optional": true, - "requires": { - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } - } + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.2" } }, "ajv-keywords": { - "version": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "dev": true }, - "align-text": { - "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "longest": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "alter": { - "version": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", - "integrity": "sha1-x1iICGF1cgNKrmJICvJrHU0cs80=", - "dev": true, - "requires": { - "stable": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz" - } + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true }, "amdefine": { - "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, - "angular": { - "version": "https://registry.npmjs.org/angular/-/angular-1.6.7.tgz", - "integrity": "sha1-D4mDfa4XdrAcyx+iCW2w2Tc9mJc=", - "dev": true - }, - "angular-assert-q-constructor": { - "version": "https://registry.npmjs.org/angular-assert-q-constructor/-/angular-assert-q-constructor-1.0.1.tgz", - "integrity": "sha1-2U9bB3pOaL2Tf+Pmw+Ld9W3EaEw=", - "dev": true - }, - "angular-bootstrap-show-errors": { - "version": "https://registry.npmjs.org/angular-bootstrap-show-errors/-/angular-bootstrap-show-errors-2.3.0.tgz", - "integrity": "sha1-sVL2MEf6j5cofwfqAiwA293U730=", - "dev": true - }, - "angular-cookies": { - "version": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.6.7.tgz", - "integrity": "sha1-hBuMG6bRAdiG8Wdr2k3BrZCVrUw=", - "dev": true - }, - "angular-credit-cards": { - "version": "https://registry.npmjs.org/angular-credit-cards/-/angular-credit-cards-3.1.6.tgz", - "integrity": "sha1-FV5jo72fiYo10TE4XLyhMFSPBfI=", + "angular2-template-loader": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz", + "integrity": "sha1-wNROkP/w+sleiyPwQ6zaf9HFHXw=", "dev": true, "requires": { - "ap": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", - "cast-array": "https://registry.npmjs.org/cast-array/-/cast-array-1.0.1.tgz", - "creditcards": "https://registry.npmjs.org/creditcards/-/creditcards-2.1.2.tgz", - "function-bind": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - } - }, - "angular-jwt": { - "version": "https://registry.npmjs.org/angular-jwt/-/angular-jwt-0.1.9.tgz", - "integrity": "sha1-24vPGPBapXMgrC/aFh1+liLAmcM=", - "dev": true - }, - "angular-messages": { - "version": "https://registry.npmjs.org/angular-messages/-/angular-messages-1.6.7.tgz", - "integrity": "sha1-uClD1EKSnXh1R4FLOU80gb029+A=", - "dev": true - }, - "angular-promise-polyfill": { - "version": "https://registry.npmjs.org/angular-promise-polyfill/-/angular-promise-polyfill-0.0.4.tgz", - "integrity": "sha1-51ZuarjgJphqAc63FcczsOu1sNo=", - "dev": true - }, - "angular-q-promisify": { - "version": "https://registry.npmjs.org/angular-q-promisify/-/angular-q-promisify-3.0.0.tgz", - "integrity": "sha1-GCOWvEuanYyRgsS5l3i6KmtbMWU=", - "dev": true, - "requires": { - "assert-function": "https://registry.npmjs.org/assert-function/-/assert-function-1.0.0.tgz", - "browserify": "https://registry.npmjs.org/browserify/-/browserify-13.1.1.tgz", - "to-array": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" + "loader-utils": "0.2.17" }, "dependencies": { - "browserify": { - "version": "https://registry.npmjs.org/browserify/-/browserify-13.1.1.tgz", - "integrity": "sha1-cqIxDi9wbth9uSnPDuc6Xhldm7A=", + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "assert": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", - "browser-pack": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", - "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "buffer": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "deps-sort": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "has": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "htmlescape": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "insert-module-globals": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", - "labeled-stream-splicer": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", - "module-deps": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", - "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", - "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "read-only-stream": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "shell-quote": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "syntax-error": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" } } } }, - "angular-resource": { - "version": "https://registry.npmjs.org/angular-resource/-/angular-resource-1.6.7.tgz", - "integrity": "sha1-GsmjPRcV8gQsEyHILKMH5pT/3JM=", - "dev": true + "angular2-toaster": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/angular2-toaster/-/angular2-toaster-4.0.2.tgz", + "integrity": "sha512-/ndYYbV/7WZx6ujm6avFUqfb+FKbrx7oT+3mYj8i0o9N26Ug+BseFjy6oRnlVVedl39yRP6hhea81QgKmoYbbQ==" }, - "angular-sanitize": { - "version": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.6.7.tgz", - "integrity": "sha1-Wj1hrXuLaZkjMpY12ZJIvPziZAg=", - "dev": true - }, - "angular-stripe": { - "version": "https://registry.npmjs.org/angular-stripe/-/angular-stripe-5.0.0.tgz", - "integrity": "sha1-2HbXGAcaNWTsiG9Vex0sA9gXvjE=", - "dev": true, + "angulartics2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/angulartics2/-/angulartics2-5.0.1.tgz", + "integrity": "sha512-QYBp7km7xTf/57zKKnYreM0OQ1Pq0kd4L9HJTC79vy7+RG1XqrkA944jTGKDERLWtjEAlQuSyZMS9J5IZZ56sw==", "requires": { - "angular-assert-q-constructor": "https://registry.npmjs.org/angular-assert-q-constructor/-/angular-assert-q-constructor-1.0.1.tgz", - "angular-q-promisify": "https://registry.npmjs.org/angular-q-promisify/-/angular-q-promisify-3.0.0.tgz", - "ap": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", - "dot-prop": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "lazy-async": "https://registry.npmjs.org/lazy-async/-/lazy-async-1.0.1.tgz", - "load-script-global": "https://registry.npmjs.org/load-script-global/-/load-script-global-1.0.2.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "stripe-as-promised": "https://registry.npmjs.org/stripe-as-promised/-/stripe-as-promised-2.1.1.tgz", - "stripe-errback": "https://registry.npmjs.org/stripe-errback/-/stripe-errback-1.0.2.tgz" + "tslib": "1.9.2" } }, - "angular-toastr": { - "version": "https://registry.npmjs.org/angular-toastr/-/angular-toastr-2.1.1.tgz", - "integrity": "sha1-n4NQykghRaRNARp1W4+zYj1gVEw=", - "dev": true - }, - "angular-ui-bootstrap": { - "version": "https://registry.npmjs.org/angular-ui-bootstrap/-/angular-ui-bootstrap-2.5.6.tgz", - "integrity": "sha1-I5NzIuxkGm++4WSYzDJFKqGZ58U=", - "dev": true - }, - "angular-ui-router": { - "version": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.4.2.tgz", - "integrity": "sha1-tq7Rymmmg8guOZKJjqvUuhWGhgg=", + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", "dev": true, "requires": { - "angular": "https://registry.npmjs.org/angular/-/angular-1.6.7.tgz" + "string-width": "2.1.1" } }, - "angulartics": { - "version": "https://registry.npmjs.org/angulartics/-/angulartics-1.5.0.tgz", - "integrity": "sha1-skQKPgQmaCAVwasUl7JnJ1cUtTw=", - "dev": true - }, - "angulartics-google-analytics": { - "version": "https://registry.npmjs.org/angulartics-google-analytics/-/angulartics-google-analytics-0.4.0.tgz", - "integrity": "sha1-rzLbDQqnBNBYNqzqcvBp8JEbelE=", - "dev": true - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" - } - }, - "ansi-gray": { - "version": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" - } + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, - "ansi-wrap": { - "version": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", "dev": true }, "anymatch": { - "version": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { - "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - }, - "dependencies": { - "arr-diff": { - "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - } - }, - "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" - } - }, - "expand-brackets": { - "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" - } - }, - "extglob": { - "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } - }, - "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - }, - "micromatch": { - "version": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "braces": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "extglob": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" - } - } + "micromatch": "2.3.11", + "normalize-path": "2.1.1" } }, - "ap": { - "version": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", - "integrity": "sha1-rglCYAspkS8NKxTsYMRejzMLYRA=", + "app-root-path": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", + "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", "dev": true }, - "archy": { - "version": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, - "argparse": { - "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "arch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.0.tgz", + "integrity": "sha1-NhOqRhSQZLPB8GB5Gb8dR4boKIk=", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "requires": { - "sprintf-js": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" } }, "arr-diff": { - "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } }, "arr-flatten": { - "version": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "arr-union": { - "version": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-differ": { - "version": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-filter": { - "version": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-find-index": { - "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, - "array-last": { - "version": "https://registry.npmjs.org/array-last/-/array-last-1.0.2.tgz", - "integrity": "sha1-pgJOsMCM0jCUr6Zlqed67GyS23Q=", + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "is-number": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz" + "array-uniq": "1.0.3" } }, - "array-map": { - "version": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, - "array-slice": { - "version": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, "array-uniq": { - "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, - "asap": { - "version": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true, - "optional": true + "dev": true }, "asn1.js": { - "version": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", - "integrity": "sha1-gRfvT37YfNj4kES1v/l6wkOhbJo=", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" } }, "assert": { - "version": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", - "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, "requires": { - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz" + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } } }, - "assert-equal": { - "version": "https://registry.npmjs.org/assert-equal/-/assert-equal-1.0.0.tgz", - "integrity": "sha1-Om7y/ICgpM8pZ+aKvM0Do4YNoYk=", - "dev": true, - "requires": { - "assert-ok": "https://registry.npmjs.org/assert-ok/-/assert-ok-1.0.0.tgz", - "print-value": "https://registry.npmjs.org/print-value/-/print-value-1.0.0.tgz", - "simple-format": "https://registry.npmjs.org/simple-format/-/simple-format-1.0.0.tgz" - } - }, - "assert-function": { - "version": "https://registry.npmjs.org/assert-function/-/assert-function-1.0.0.tgz", - "integrity": "sha1-rrKtD+AIiLQSVKjjk0pWKWjXeQU=", - "dev": true - }, - "assert-ok": { - "version": "https://registry.npmjs.org/assert-ok/-/assert-ok-1.0.0.tgz", - "integrity": "sha1-W1z3lfknXFnHFNZsOgbX3nDkPsg=", - "dev": true - }, "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true + "dev": true }, "assign-symbols": { - "version": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "astw": { - "version": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", - "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", - "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" - } + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", + "dev": true }, "async": { - "version": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" + "lodash": "4.17.10" } }, "async-each": { - "version": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, - "asynckit": { - "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true, - "optional": true - }, - "atob": { - "version": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", "dev": true }, - "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "dev": true + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "dev": true, - "optional": true + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000848", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true }, "aws4": { - "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, - "optional": true + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.4.1", + "regenerator-runtime": "0.10.5" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.4.1", + "regenerator-runtime": "0.11.1" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } }, "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base": { - "version": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "class-utils": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.5.tgz", - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "mixin-deep": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", - "pascalcase": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" }, "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "base64-js": { - "version": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=", - "dev": true - }, - "base64-url": { - "version": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", - "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=", - "dev": true - }, - "basic-auth": { - "version": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", - "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=", - "dev": true - }, - "basic-auth-connect": { - "version": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=", - "dev": true - }, - "batch": { - "version": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "bcrypt-pbkdf": { - "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, "optional": true, "requires": { - "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + "tweetnacl": "0.14.5" } }, - "beeper": { - "version": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, "big.js": { - "version": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, "binary-extensions": { - "version": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", @@ -735,2090 +1075,1948 @@ "dev": true }, "bn.js": { - "version": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, - "body-parser": { - "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", - "integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=", - "dev": true, - "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "type-is": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true }, "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + "hoek": "2.16.3" } }, "bootstrap": { - "version": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz", - "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=", - "dev": true + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.1.tgz", + "integrity": "sha512-SpiDSOcbg4J/PjVSt4ny5eY6j74VbVSjROY4Fb/WIUXBV9cnb5luyR4KnPvNoXuGnBK1T+nJIWqRsvU3yP8Mcg==" }, - "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", "dev": true, "requires": { - "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" } }, "braces": { - "version": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", - "integrity": "sha1-pGlBy1+0khVrPWplbgbDU2Tj5m4=", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "fill-range": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "snapdragon-node": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "split-string": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "to-regex": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz" - }, - "dependencies": { - "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "brorand": { - "version": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, - "browser-fingerprint": { - "version": "https://registry.npmjs.org/browser-fingerprint/-/browser-fingerprint-0.0.1.tgz", - "integrity": "sha1-jfPNyiW/fVs1QtYVRdcwBT/OYEo=", - "dev": true - }, - "browser-pack": { - "version": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", - "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "combine-source-map": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "umd": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz" - } - }, - "browser-resolve": { - "version": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", - "dev": true, - "requires": { - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" - }, - "dependencies": { - "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "browserify": { - "version": "https://registry.npmjs.org/browserify/-/browserify-14.5.0.tgz", - "integrity": "sha1-C7vOUhrNbk0dVNjpNlAI77hanMU=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "assert": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "browser-pack": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", - "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "buffer": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", - "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "deps-sort": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "has": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "htmlescape": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "insert-module-globals": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", - "labeled-stream-splicer": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", - "module-deps": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", - "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "read-only-stream": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "shell-quote": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "syntax-error": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - }, - "dependencies": { - "assert": { - "version": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz" - } - }, - "browserify-zlib": { - "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", - "dev": true, - "requires": { - "pako": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz" - } - }, - "buffer": { - "version": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", - "integrity": "sha1-hNqlLnzy+ozkGVvFzw94CeCTCyQ=", - "dev": true, - "requires": { - "base64-js": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz" - } - }, - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "dev": true, - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - }, - "https-browserify": { - "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "os-browserify": { - "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "pako": { - "version": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } - } - }, "browserify-aes": { - "version": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha1-OLerVe24Bv8tzaGn8WIHc6R3xJ8=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { - "buffer-xor": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" } }, "browserify-cipher": { - "version": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, "requires": { - "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "browserify-des": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" + "browserify-aes": "1.2.0", + "browserify-des": "1.0.1", + "evp_bytestokey": "1.0.3" } }, "browserify-des": { - "version": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", "dev": true, "requires": { - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "des.js": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" } }, "browserify-rsa": { - "version": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz" + "bn.js": "4.11.8", + "randombytes": "2.0.6" } }, "browserify-sign": { - "version": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "browserify-rsa": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "elliptic": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "parse-asn1": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz" + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" } }, "browserify-zlib": { - "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "requires": { - "pako": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz" + "pako": "1.0.6" + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000848", + "electron-to-chromium": "1.3.48" } }, "buffer": { - "version": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "ieee754": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } + "base64-js": "1.3.0", + "ieee754": "1.1.11", + "isarray": "1.0.0" } }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, "buffer-xor": { - "version": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "bufferstreams": { - "version": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.3.tgz", - "integrity": "sha1-qFFawCT6kOj6fVjBGxPeofKKvnI=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, "builtin-modules": { - "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "builtin-status-codes": { - "version": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, - "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q=", - "dev": true - }, - "cache-base": { - "version": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", "dev": true, "requires": { - "collection-visit": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "component-emitter": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "has-value": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "set-value": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "union-value": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "unset-value": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, - "cached-path-relative": { - "version": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", - "dev": true - }, - "call-all-fns": { - "version": "https://registry.npmjs.org/call-all-fns/-/call-all-fns-1.0.1.tgz", - "integrity": "sha1-PSGicg/nrlcIwu14B+mJ1nRPMsE=", - "dev": true + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "2.3.2", + "upper-case": "1.1.3" + } }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, "camelcase-keys": { - "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" + "camelcase": "2.1.1", + "map-obj": "1.0.1" } }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000848", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" + } + }, + "caniuse-db": { + "version": "1.0.30000848", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000848.tgz", + "integrity": "sha1-4UnJgccqogQ547wSx8+LP34SN8Y=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true, - "optional": true - }, - "cast-array": { - "version": "https://registry.npmjs.org/cast-array/-/cast-array-1.0.1.tgz", - "integrity": "sha1-Jk7xEp5YiLxIysQP6RTp9puNGJ0=", - "dev": true, - "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - } - }, - "center-align": { - "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" - }, - "dependencies": { - "lazy-cache": { - "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - } - } + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, "chokidar": { - "version": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "fsevents": "1.1.3", - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" - }, - "dependencies": { - "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } - }, - "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } - } + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.2.4", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, + "chrome-trace-event": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-0.1.3.tgz", + "integrity": "sha512-sjndyZHrrWiu4RY7AkHgjn80GfAM2ZSzUkZLV/Js59Ldmh6JDThf0SUmOHU53rFu2rVxxfCzJ30Ukcfch3Gb/A==", + "dev": true + }, + "ci-info": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", + "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", + "dev": true + }, "cipher-base": { - "version": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + } + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "dev": true, + "requires": { + "chalk": "1.1.3" } }, "class-utils": { - "version": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.5.tgz", - "integrity": "sha1-F+eTEDdQ+WJ7IXbqNM/RtWWQPIA=", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "static-extend": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + "is-descriptor": "0.1.6" } }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true } } }, "clean-css": { - "version": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", - "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", + "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", "dev": true, "requires": { - "commander": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" - }, - "dependencies": { - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" - } - } + "source-map": "0.5.7" } }, - "cli": { - "version": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "clean-webpack-plugin": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-0.1.19.tgz", + "integrity": "sha512-M1Li5yLHECcN2MahoreuODul5LkjohJGFxLPTjl3j1ttKrF5rgjZET1SJduuqxLAuT1gAPOdkhg03qcaaU1KeA==", "dev": true, "requires": { - "exit": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" - }, - "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "dev": true, - "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - } - } + "rimraf": "2.6.2" } }, - "clipboard": { - "version": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", - "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=", + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "clipboardy": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz", + "integrity": "sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==", "dev": true, "requires": { - "good-listener": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "select": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "tiny-emitter": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz" + "arch": "2.1.0", + "execa": "0.8.0" + }, + "dependencies": { + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + } } }, "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "wrap-ansi": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } } }, "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, - "clone-buffer": { - "version": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "cloneable-readable": { - "version": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "clone-deep": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" + "for-own": "1.0.0", + "is-plain-object": "2.0.4", + "kind-of": "6.0.2", + "shallow-clone": "1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "co": { - "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "1.5.1" + } + }, "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "collection-visit": { - "version": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "object-visit": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, - "color-support": { - "version": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=", + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "1.0.4", + "color-convert": "1.9.1", + "color-string": "0.3.0" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "combine-source-map": { - "version": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", - "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "dev": true, "requires": { - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "inline-source-map": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "lodash.memoize": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + "color-name": "1.1.3" } }, - "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", "dev": true, "requires": { - "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + "color": "0.11.4", + "css-color-names": "0.0.4", + "has": "1.0.3" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" } }, "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" - } + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true }, "component-emitter": { - "version": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, - "compressible": { - "version": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", - "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", - "dev": true, - "requires": { - "mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz" - } - }, - "compression": { - "version": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", - "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", - "dev": true, - "requires": { - "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "compressible": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "vary": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "typedarray": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" - }, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - } - } + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" } }, - "concat-with-sourcemaps": { - "version": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", - "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", "dev": true, "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - } - }, - "config-chain": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", - "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", - "dev": true, - "requires": { - "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "proto-list": "1.2.4" - } - }, - "connect": { - "version": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz", - "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=", - "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "finalhandler": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" - } - }, - "connect-livereload": { - "version": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", - "dev": true - }, - "connect-timeout": { - "version": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", - "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", - "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" } }, "console-browserify": { - "version": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "date-now": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz" + "date-now": "0.1.4" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, "constants-browserify": { - "version": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, "content-type": { - "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, - "convert-source-map": { - "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", - "dev": true - }, - "cookie": { - "version": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=", - "dev": true - }, - "cookie-parser": { - "version": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", - "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "cookies": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", + "integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=", "dev": true, "requires": { - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "depd": "1.1.2", + "keygrip": "1.0.2" } }, - "cookie-signature": { - "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } }, "copy-descriptor": { - "version": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-js": { - "version": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true - }, - "core-util-is": { - "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "crc": { - "version": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", - "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", - "dev": true - }, - "create-ecdh": { - "version": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "copy-webpack-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.1.tgz", + "integrity": "sha512-OlTo6DYg0XfTKOF8eLf79wcHm4Ut10xU2cRBRPMW/NA5F9VMjZGTfRHWDIYC3s+1kObGYrBLshXWU1K0hILkNQ==", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "elliptic": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz" - } - }, - "create-hash": { - "version": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "dev": true, - "requires": { - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz" - } - }, - "create-hmac": { - "version": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "dev": true, - "requires": { - "cipher-base": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz" - } - }, - "creditcards": { - "version": "https://registry.npmjs.org/creditcards/-/creditcards-2.1.2.tgz", - "integrity": "sha1-XQ9ukRhBctO21X2MXa79EGXHy24=", - "dev": true, - "requires": { - "creditcards-types": "https://registry.npmjs.org/creditcards-types/-/creditcards-types-1.6.2.tgz", - "fast-luhn": "https://registry.npmjs.org/fast-luhn/-/fast-luhn-1.0.3.tgz", - "is-valid-month": "https://registry.npmjs.org/is-valid-month/-/is-valid-month-1.0.0.tgz", - "parse-int": "https://registry.npmjs.org/parse-int/-/parse-int-1.0.2.tgz", - "parse-year": "https://registry.npmjs.org/parse-year/-/parse-year-1.0.0.tgz", - "to-camel-case": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "creditcards-types": { - "version": "https://registry.npmjs.org/creditcards-types/-/creditcards-types-1.6.2.tgz", - "integrity": "sha1-W+bKy8rMPiCtI40oeexYYPRn8c0=", - "dev": true, - "requires": { - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "cross-spawn": { - "version": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "shebang-command": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "globby": "7.1.1", + "is-glob": "4.0.0", + "loader-utils": "1.1.0", + "minimatch": "3.0.4", + "p-limit": "1.2.0", + "serialize-javascript": "1.5.0" }, "dependencies": { - "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "pseudomap": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "yallist": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz" + "is-extglob": "2.1.1" } } } }, + "core-js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.5.tgz", + "integrity": "sha512-94j37OtvxS5w7qr7Ta6dt67tWdnOxigBVN4VnSxNXFez9o18PGQ0D33SchKP17r9LAcWVTYV72G6vDayAUBFIg==", + "dev": true, + "requires": { + "is-directory": "0.3.1", + "js-yaml": "3.12.0", + "parse-json": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.2" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" + } + }, + "cross-env": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.6.tgz", + "integrity": "sha512-VWTDq+G4v383SzgRS7jsAVWqEWF0aKZpDz1GVjhONvPRgHB1LnxP2sXUVFKbykHkPSnfRKS8YdiDevWFwZmQ9g==", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "is-windows": "1.0.2" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, - "optional": true, "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + "boom": "2.10.1" } }, "crypto-browserify": { - "version": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { - "browserify-cipher": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "browserify-sign": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "create-ecdh": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "diffie-hellman": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "pbkdf2": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "public-encrypt": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "randomfill": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz" + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" } }, - "csrf": { - "version": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-loader": { + "version": "0.28.11", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", + "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", "dev": true, "requires": { - "rndm": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "tsscmp": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "uid-safe": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz" + "babel-code-frame": "6.26.0", + "css-selector-tokenizer": "0.7.0", + "cssnano": "3.10.0", + "icss-utils": "2.1.0", + "loader-utils": "1.1.0", + "lodash.camelcase": "4.3.0", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-modules-extract-imports": "1.2.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0", + "postcss-value-parser": "3.3.0", + "source-list-map": "2.0.0" } }, - "csurf": { - "version": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", - "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dev": true, "requires": { - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "csrf": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz" + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" } }, - "cuid": { - "version": "https://registry.npmjs.org/cuid/-/cuid-1.3.8.tgz", - "integrity": "sha1-S4deCWm612T37AcGz0T1+wgx9rc=", + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", "dev": true, "requires": { - "browser-fingerprint": "https://registry.npmjs.org/browser-fingerprint/-/browser-fingerprint-0.0.1.tgz", - "core-js": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "node-fingerprint": "https://registry.npmjs.org/node-fingerprint/-/node-fingerprint-0.0.2.tgz" + "cssesc": "0.1.0", + "fastparse": "1.1.1", + "regexpu-core": "1.0.0" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "dev": true, + "requires": { + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.3", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.3", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.0", + "postcss-zindex": "2.2.0" + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "dev": true, + "requires": { + "clap": "1.2.3", + "source-map": "0.5.7" } }, "currently-unhandled": { - "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz" + "array-find-index": "1.0.2" } }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { - "version": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz" + "es5-ext": "0.10.45" } }, "dashdash": { - "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, - "optional": true, "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "assert-plus": "1.0.0" }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true + "dev": true } } }, "date-now": { - "version": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, - "dateformat": { - "version": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "ms": "2.0.0" } }, "decamelize": { - "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "1.2.0", + "map-obj": "1.0.1" + } + }, "decode-uri-component": { - "version": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deepmerge": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.0.tgz", - "integrity": "sha512-Q89Z26KAfA3lpPGhbF6XMfYAm3jIV3avViy6KOJ2JLzFbeWHOvPQUu5aSJIWXap3gDZC2y1eF5HXEPI2wGqgvw==", + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, - "defaults": { - "version": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", "dev": true, "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz" + "foreach": "2.0.5", + "object-keys": "1.0.11" } }, "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.1.tgz" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "defined": { - "version": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "delegate": { - "version": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=", + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, - "deprecated": { - "version": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "deps-sort": { - "version": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "shasum": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } - }, - "derequire": { - "version": "https://registry.npmjs.org/derequire/-/derequire-2.0.6.tgz", - "integrity": "sha1-MaQUu3yhdiOfp4sRZjbvd9UX52g=", - "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "escope": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz" - } - }, "des.js": { - "version": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" } }, "destroy": { - "version": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, - "detect-file": { - "version": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, - "detective": { - "version": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "integrity": "sha1-DspzFDOEQv67bWXaVMELscgrJG4=", - "dev": true, - "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" - }, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=", - "dev": true - } - } - }, - "dezalgo": { - "version": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", - "dev": true, - "requires": { - "asap": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - }, "diffie-hellman": { - "version": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "miller-rabin": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz" + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + } + }, + "dom-converter": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", + "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", + "dev": true, + "requires": { + "utila": "0.3.3" + }, + "dependencies": { + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true + } } }, "dom-serializer": { - "version": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", "dev": true, "requires": { - "domelementtype": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "entities": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz" + "domelementtype": "1.1.3", + "entities": "1.1.1" }, "dependencies": { "domelementtype": { - "version": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", "dev": true - }, - "entities": { - "version": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true } } }, - "dom-walk": { - "version": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", - "dev": true - }, "domain-browser": { - "version": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "domelementtype": { - "version": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", "dev": true }, "domhandler": { - "version": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", + "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", "dev": true, "requires": { - "domelementtype": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" + "domelementtype": "1.3.0" } }, "domutils": { - "version": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "dev": true, "requires": { - "dom-serializer": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "domelementtype": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz" + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" } }, - "dot-parts": { - "version": "https://registry.npmjs.org/dot-parts/-/dot-parts-1.0.1.tgz", - "integrity": "sha1-iEvXvPwwgv+tL+XbU+SU2PPgdD8=", - "dev": true - }, "dot-prop": { - "version": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { - "is-obj": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + "is-obj": "1.0.1" } }, "duo_web_sdk": { - "version": "git+https://github.com/duosecurity/duo_web_sdk.git#7de73ecb6594182600601d4e4d29bd2869271287", - "dev": true + "version": "git+https://github.com/duosecurity/duo_web_sdk.git#7de73ecb6594182600601d4e4d29bd2869271287" }, - "duplexer": { - "version": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "duplexer2": { - "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, "duplexify": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", - "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", "dev": true, "requires": { "end-of-stream": "1.4.1", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "inherits": "2.0.3", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } - } - } - }, - "ear": { - "version": "https://registry.npmjs.org/ear/-/ear-1.0.1.tgz", - "integrity": "sha1-kAUKQ1Du4X/a+0WbLildZT53Ov0=", - "dev": true, - "requires": { - "assert-function": "https://registry.npmjs.org/assert-function/-/assert-function-1.0.0.tgz" } }, "ecc-jsbn": { - "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, "optional": true, "requires": { - "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" - } - }, - "editorconfig": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", - "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", - "dev": true, - "requires": { - "bluebird": "3.5.1", - "commander": "2.15.1", - "lru-cache": "3.2.0", - "semver": "5.5.0", - "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "lru-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", - "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", - "dev": true, - "requires": { - "pseudomap": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - } + "jsbn": "0.1.1" } }, "ee-first": { - "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.3.48", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", + "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=", + "dev": true + }, "elliptic": { - "version": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "brorand": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "hash.js": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "hmac-drbg": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "minimalistic-crypto-utils": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" } }, "emojis-list": { - "version": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "encodeurl": { - "version": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", - "dev": true + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.23" + } }, "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" - }, - "dependencies": { - "once": { - "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - } + "once": "1.4.0" } }, "enhanced-resolve": { - "version": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", "dev": true, "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz" - }, - "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" } }, "entities": { - "version": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", "dev": true }, "errno": { - "version": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", - "integrity": "sha1-w4bOimKD8U/AlWO3FWCQjJv1MCY=", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { - "prr": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" + "prr": "1.0.1" } }, "error-ex": { - "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "is-arrayish": "0.2.1" } }, - "errorhandler": { - "version": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", - "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "error-inject": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz", + "integrity": "sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc=", + "dev": true + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { - "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "dependencies": { - "accepts": { - "version": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "dev": true, - "requires": { - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "negotiator": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - } - }, - "negotiator": { - "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - } + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" } }, "es5-ext": { - "version": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", "dev": true, "requires": { - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" } }, "es6-iterator": { - "version": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" + "d": "1.0.0", + "es5-ext": "0.10.45", + "es6-symbol": "3.1.1" } }, - "es6-map": { - "version": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-set": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" - } - }, - "es6-promise": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz", - "integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw=", - "dev": true - }, - "es6-set": { - "version": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "event-emitter": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" - } + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=" }, "es6-symbol": { - "version": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "dev": true, "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz" + "d": "1.0.0", + "es5-ext": "0.10.45" } }, - "es6-weak-map": { - "version": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", "dev": true, "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "es6-iterator": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "es6-symbol": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" + "recast": "0.11.23", + "through": "2.3.8" } }, "escape-html": { - "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, "escape-string-regexp": { - "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escope": { - "version": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "es6-map": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "es6-weak-map": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "esrecurse": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" + "esrecurse": "4.2.1", + "estraverse": "4.2.0" } }, "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, "esrecurse": { - "version": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - }, - "dependencies": { - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } + "estraverse": "4.2.0" } }, "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, - "etag": { - "version": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "event-emitter": { - "version": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz" - } - }, - "event-stream": { - "version": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "from": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "pause-stream": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "split": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "stream-combiner": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - } - }, "events": { - "version": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, "evp_bytestokey": { - "version": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { - "md5.js": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "md5.js": "1.3.4", + "safe-buffer": "5.1.2" } }, "execa": { - "version": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "get-stream": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "npm-run-path": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "p-finally": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "strip-eof": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, - "exit": { - "version": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, "expand-brackets": { - "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "posix-character-classes": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "regex-not": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz" - }, - "dependencies": { - "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true - } + "is-posix-bracket": "0.1.1" } }, "expand-range": { - "version": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" - }, - "dependencies": { - "fill-range": { - "version": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.0.0.tgz", - "randomatic": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - } - }, - "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "expand-tilde": { - "version": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz" - } - }, - "expand-year": { - "version": "https://registry.npmjs.org/expand-year/-/expand-year-1.0.0.tgz", - "integrity": "sha1-rd7sCl7fXtVPbAdItkH9SJMCapM=", - "dev": true, - "requires": { - "parse-int": "https://registry.npmjs.org/parse-int/-/parse-int-1.0.2.tgz", - "zero-fill": "https://registry.npmjs.org/zero-fill/-/zero-fill-2.2.3.tgz" - } - }, - "exposify": { - "version": "https://registry.npmjs.org/exposify/-/exposify-0.5.0.tgz", - "integrity": "sha1-+S0AlMJls/VT4fpFagOhiD0QWcw=", - "dev": true, - "requires": { - "globo": "https://registry.npmjs.org/globo/-/globo-1.1.0.tgz", - "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "replace-requires": "https://registry.npmjs.org/replace-requires/-/replace-requires-1.0.4.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "transformify": "https://registry.npmjs.org/transformify/-/transformify-0.1.2.tgz" - }, - "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" - } - }, - "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" - } - } - } - }, - "express-session": { - "version": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", - "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", - "dev": true, - "requires": { - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "crc": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "uid-safe": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", - "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "uid-safe": { - "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", - "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", - "dev": true, - "requires": { - "base64-url": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz" - } - }, - "utils-merge": { - "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - } + "fill-range": "2.2.4" } }, "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, "extend-shallow": { - "version": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - } - }, - "extglob": { - "version": "https://registry.npmjs.org/extglob/-/extglob-2.0.3.tgz", - "integrity": "sha1-VeAZ0Mlb+HOUnHN7flFy26hOuyk=", - "dev": true, - "requires": { - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "regex-not": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz" - } - }, - "extsprintf": { - "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fancy-log": { - "version": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "color-support": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "time-stamp": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz" - } - }, - "fast-deep-equal": { - "version": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-luhn": { - "version": "https://registry.npmjs.org/fast-luhn/-/fast-luhn-1.0.3.tgz", - "integrity": "sha1-dZyjqYPdoGdC06PPpvZAcFNqQi8=", - "dev": true - }, - "faye-websocket": { - "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz" - } - }, - "filename-regex": { - "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "filesize": { - "version": "https://registry.npmjs.org/filesize/-/filesize-2.0.4.tgz", - "integrity": "sha1-eAWUHGD83+Y/RtfqNYxZreEcEyU=", - "dev": true - }, - "fill-range": { - "version": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "to-regex-range": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { - "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "is-plain-object": "2.0.4" } } } }, - "finalhandler": { - "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", - "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", - "dev": true, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "encodeurl": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "chardet": "0.4.2", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" } }, - "find-index": { - "version": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-text-webpack-plugin": { + "version": "4.0.0-beta.0", + "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz", + "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==", + "dev": true, + "requires": { + "async": "2.6.1", + "loader-utils": "1.1.0", + "schema-utils": "0.4.5", + "webpack-sources": "1.1.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-loader": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "schema-utils": "0.4.5" + }, + "dependencies": { + "ajv": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "dev": true, + "requires": { + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" + } + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.0.0", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.3.0", + "pkg-dir": "2.0.0" + } + }, "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "path-exists": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + "locate-path": "2.0.0" } }, - "findup-sync": { - "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "dev": true + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", "dev": true, "requires": { - "detect-file": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.4.tgz", - "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, - "fined": { - "version": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "object.defaults": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "parse-filepath": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz" - } - }, - "first-chunk-stream": { - "version": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "flex-exec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flex-exec/-/flex-exec-1.0.0.tgz", - "integrity": "sha1-BpdLaFMoOdKhLDLevNsSN4IA/fA=", - "dev": true - }, "font-awesome": { - "version": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=", - "dev": true + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" }, "for-in": { - "version": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "for-own": { - "version": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "optional": true + "dev": true }, "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, - "optional": true, "requires": { - "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" } }, "fragment-cache": { - "version": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" + "map-cache": "0.2.2" } }, "fresh": { - "version": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, - "from": { - "version": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.6" + } }, "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, "optional": true, "requires": { - "nan": "2.8.0", - "node-pre-gyp": "0.6.39" + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" }, "dependencies": { "abbrev": { - "version": "1.1.0", + "version": "1.1.1", "bundled": true, "dev": true, "optional": true }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, "ansi-regex": { "version": "2.1.1", "bundled": true, "dev": true }, "aproba": { - "version": "1.1.1", + "version": "1.2.0", "bundled": true, "dev": true, "optional": true @@ -2830,91 +3028,25 @@ "optional": true, "requires": { "delegates": "1.0.0", - "readable-stream": "2.2.9" + "readable-stream": "2.3.6" } }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "optional": true - }, "balanced-match": { - "version": "0.4.2", - "bundled": true, - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { "version": "1.0.0", "bundled": true, "dev": true }, - "caseless": { - "version": "0.12.0", + "brace-expansion": { + "version": "1.1.11", "bundled": true, "dev": true, - "optional": true + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } }, - "co": { - "version": "4.6.0", + "chownr": { + "version": "1.0.1", "bundled": true, "dev": true, "optional": true @@ -2924,14 +3056,6 @@ "bundled": true, "dev": true }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, "concat-map": { "version": "0.0.1", "bundled": true, @@ -2945,35 +3069,11 @@ "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } + "optional": true }, "debug": { - "version": "2.6.8", + "version": "2.6.9", "bundled": true, "dev": true, "optional": true, @@ -2982,16 +3082,11 @@ } }, "deep-extend": { - "version": "0.4.2", + "version": "0.5.1", "bundled": true, "dev": true, "optional": true }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, "delegates": { "version": "1.0.0", "bundled": true, @@ -2999,74 +3094,25 @@ "optional": true }, "detect-libc": { - "version": "1.0.2", + "version": "1.0.3", "bundled": true, "dev": true, "optional": true }, - "ecc-jsbn": { - "version": "0.1.1", + "fs-minipass": { + "version": "1.2.5", "bundled": true, "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" + "minipass": "2.2.4" } }, "fs.realpath": { "version": "1.0.0", "bundled": true, - "dev": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } + "optional": true }, "gauge": { "version": "2.7.4", @@ -3074,7 +3120,7 @@ "dev": true, "optional": true, "requires": { - "aproba": "1.1.1", + "aproba": "1.2.0", "console-control-strings": "1.1.0", "has-unicode": "2.0.1", "object-assign": "4.1.1", @@ -3084,27 +3130,11 @@ "wide-align": "1.1.2" } }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, "glob": { "version": "7.1.2", "bundled": true, "dev": true, + "optional": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -3114,64 +3144,35 @@ "path-is-absolute": "1.0.1" } }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true, - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, "has-unicode": { "version": "2.0.1", "bundled": true, "dev": true, "optional": true }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true, - "dev": true - }, - "http-signature": { - "version": "1.1.1", + "iconv-lite": { + "version": "0.4.21", "bundled": true, "dev": true, "optional": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" } }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, + "optional": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -3183,7 +3184,7 @@ "dev": true }, "ini": { - "version": "1.3.4", + "version": "1.3.5", "bundled": true, "dev": true, "optional": true @@ -3196,104 +3197,18 @@ "number-is-nan": "1.0.1" } }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, "isarray": { "version": "1.0.0", "bundled": true, - "dev": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, "dev": true, "optional": true }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true, - "dev": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "dev": true, - "requires": { - "mime-db": "1.27.0" - } - }, "minimatch": { "version": "3.0.4", "bundled": true, "dev": true, "requires": { - "brace-expansion": "1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -3301,6 +3216,24 @@ "bundled": true, "dev": true }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, "mkdirp": { "version": "0.5.1", "bundled": true, @@ -3315,23 +3248,33 @@ "dev": true, "optional": true }, - "node-pre-gyp": { - "version": "0.6.39", + "needle": { + "version": "2.2.0", "bundled": true, "dev": true, "optional": true, "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", "mkdirp": "0.5.1", + "needle": "2.2.0", "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" } }, "nopt": { @@ -3340,12 +3283,28 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" } }, "npmlog": { - "version": "4.1.0", + "version": "4.1.2", "bundled": true, "dev": true, "optional": true, @@ -3361,12 +3320,6 @@ "bundled": true, "dev": true }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "dev": true, - "optional": true - }, "object-assign": { "version": "4.1.1", "bundled": true, @@ -3394,7 +3347,7 @@ "optional": true }, "osenv": { - "version": "0.1.4", + "version": "0.1.5", "bundled": true, "dev": true, "optional": true, @@ -3406,39 +3359,23 @@ "path-is-absolute": { "version": "1.0.1", "bundled": true, - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { - "version": "1.0.7", - "bundled": true, - "dev": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", + "version": "2.0.0", "bundled": true, "dev": true, "optional": true }, "rc": { - "version": "1.2.1", + "version": "1.2.7", "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", + "deep-extend": "0.5.1", + "ini": "1.3.5", "minimist": "1.2.0", "strip-json-comments": "2.0.1" }, @@ -3452,64 +3389,48 @@ } }, "readable-stream": { - "version": "2.2.9", - "bundled": true, - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", + "version": "2.3.6", "bundled": true, "dev": true, "optional": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "rimraf": { - "version": "2.6.1", + "version": "2.6.2", "bundled": true, "dev": true, + "optional": true, "requires": { "glob": "7.1.2" } }, "safe-buffer": { - "version": "5.0.1", + "version": "5.1.1", "bundled": true, "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, "semver": { - "version": "5.3.0", + "version": "5.5.0", "bundled": true, "dev": true, "optional": true @@ -3526,39 +3447,6 @@ "dev": true, "optional": true }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, "string-width": { "version": "1.0.2", "bundled": true, @@ -3570,19 +3458,14 @@ } }, "string_decoder": { - "version": "1.0.1", + "version": "1.1.1", "bundled": true, "dev": true, + "optional": true, "requires": { - "safe-buffer": "5.0.1" + "safe-buffer": "5.1.1" } }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "dev": true, - "optional": true - }, "strip-ansi": { "version": "3.0.1", "bundled": true, @@ -3598,81 +3481,26 @@ "optional": true }, "tar": { - "version": "2.2.1", - "bundled": true, - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", + "version": "4.4.1", "bundled": true, "dev": true, "optional": true, "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "dev": true, - "optional": true - }, "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, "dev": true, "optional": true }, - "verror": { - "version": "1.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, "wide-align": { "version": "1.1.2", "bundled": true, @@ -3686,2858 +3514,2095 @@ "version": "1.0.2", "bundled": true, "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true } } }, - "function-bind": { - "version": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", - "dev": true - }, - "gaze": { - "version": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { - "globule": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz" + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "1.2.1" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" } }, "get-caller-file": { - "version": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, "get-stdin": { - "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, "get-stream": { - "version": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, "get-value": { - "version": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "getpass": { - "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, - "optional": true, "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "assert-plus": "1.0.0" }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true + "dev": true } } }, - "gift": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/gift/-/gift-0.10.2.tgz", - "integrity": "sha512-wC9aKnQpjfOTWX+JG4DPJkS89ux6sl8EN4hXhv/2vBoXCDTEz1JiTeGTSeuKYlCqIgUFM1JwPVym34Sys3hvzw==", - "dev": true, - "requires": { - "flex-exec": "1.0.0", - "underscore": "1.8.3" - } - }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-base": { - "version": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - }, - "dependencies": { - "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } - }, - "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } - } + "glob-parent": "2.0.0", + "is-glob": "2.0.1" } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "path-dirname": "1.0.2" + "is-glob": "2.0.1" } }, - "glob-stream": { - "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", "dev": true, "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "glob2base": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" - }, - "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - } - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - } + "ini": "1.3.5" } }, - "glob-watcher": { - "version": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz" - } + "global-modules-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.1.0.tgz", + "integrity": "sha512-3DrmGj2TP+96cABk9TfMp6f3knH/Y46dqvWznTU3Tf6/bDGLDAn15tFluQ7BcloykOcdY16U0WGq0BQblYOxJQ==", + "dev": true }, - "glob2base": { - "version": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", "dev": true, "requires": { - "find-index": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" - } - }, - "global": { - "version": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "requires": { - "min-document": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.5.2.tgz" - }, - "dependencies": { - "process": { - "version": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - } - } - }, - "global-modules": { - "version": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", - "dev": true, - "requires": { - "global-prefix": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "is-windows": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", - "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" - } - }, - "global-prefix": { - "version": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "is-windows": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", - "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" - } - }, - "globo": { - "version": "https://registry.npmjs.org/globo/-/globo-1.1.0.tgz", - "integrity": "sha1-DSYJiVXepCLrIAGxBImLChAcqvM=", - "dev": true, - "requires": { - "accessory": "https://registry.npmjs.org/accessory/-/accessory-1.1.0.tgz", - "is-defined": "https://registry.npmjs.org/is-defined/-/is-defined-1.0.0.tgz", - "ternary": "https://registry.npmjs.org/ternary/-/ternary-1.0.0.tgz" + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.8", + "pify": "3.0.0", + "slash": "1.0.0" } }, "globule": { - "version": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", "dev": true, "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" - }, - "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" - } - }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" - } - } + "glob": "7.1.2", + "lodash": "4.17.10", + "minimatch": "3.0.4" } }, - "glogg": { - "version": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { - "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" - } - }, - "good-listener": { - "version": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dev": true, - "requires": { - "delegate": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz" + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" } }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz" - } - }, - "graceful-readlink": { - "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, - "gulp": { - "version": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "deprecated": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "liftoff": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "orchestrator": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "pretty-hrtime": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "tildify": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "v8flags": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz" - } - }, - "gulp-concat": { - "version": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz" - }, - "dependencies": { - "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "clone-buffer": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "cloneable-readable": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz" - } - } - } - }, - "gulp-connect": { - "version": "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.0.0.tgz", - "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", - "dev": true, - "requires": { - "connect": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", - "connect-livereload": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "tiny-lr": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz" - }, - "dependencies": { - "connect": { - "version": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", - "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", - "dev": true, - "requires": { - "basic-auth-connect": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz", - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz", - "compression": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", - "connect-timeout": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", - "cookie-parser": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", - "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "csurf": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "errorhandler": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", - "express-session": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", - "finalhandler": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", - "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "method-override": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", - "morgan": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", - "multiparty": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "pause": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "response-time": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "serve-favicon": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", - "serve-index": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", - "serve-static": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", - "type-is": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "vhost": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz" - } - }, - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "escape-html": { - "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", - "dev": true - }, - "finalhandler": { - "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz", - "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", - "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "utils-merge": { - "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - } - } - }, - "gulp-cssmin": { - "version": "https://registry.npmjs.org/gulp-cssmin/-/gulp-cssmin-0.2.0.tgz", - "integrity": "sha1-h6s8ad05sg1dljVcZQStakR7HnI=", - "dev": true, - "requires": { - "clean-css": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", - "filesize": "https://registry.npmjs.org/filesize/-/filesize-2.0.4.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "gulp-rename": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.1.0.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.4.tgz", - "temp-write": "https://registry.npmjs.org/temp-write/-/temp-write-0.1.1.tgz" - }, - "dependencies": { - "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true - }, - "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true - }, - "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", - "dev": true, - "requires": { - "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" - } - }, - "dateformat": { - "version": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "meow": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz" - } - }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp-rename": { - "version": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.1.0.tgz", - "integrity": "sha1-kwkKqvTThsB/IFOKaIjxXvunJ6E=", - "dev": true, - "requires": { - "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.4.tgz" - } - }, - "gulp-util": { - "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", - "dev": true, - "requires": { - "chalk": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz" - } - }, - "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "dev": true, - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" - } - }, - "lodash._reinterpolate": { - "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", - "dev": true - }, - "lodash.escape": { - "version": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "lodash._reunescapedhtml": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - } - }, - "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } - }, - "lodash.template": { - "version": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", - "dev": true, - "requires": { - "lodash._escapestringchar": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "lodash.defaults": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "lodash.values": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" - } - }, - "lodash.templatesettings": { - "version": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", - "dev": true, - "requires": { - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz" - } - }, - "map-stream": { - "version": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.4.tgz", - "integrity": "sha1-XsbekCE+9sey65Nn6a3o2k79tos=", - "dev": true - }, - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "dev": true, - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" - } - }, - "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", - "dev": true - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" - } - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", - "dev": true, - "requires": { - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" - } - }, - "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - } - } - }, - "gulp-derequire": { - "version": "https://registry.npmjs.org/gulp-derequire/-/gulp-derequire-2.1.0.tgz", - "integrity": "sha1-BWIxBzP5+KcZxS24c6iEe4mLRuU=", - "dev": true, - "requires": { - "bufferstreams": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.3.tgz", - "derequire": "https://registry.npmjs.org/derequire/-/derequire-2.0.6.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz" - }, - "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - } - } - }, - "gulp-gh-pages": { - "version": "git+https://github.com/tekd/gulp-gh-pages.git#23c3ee535bf160d25683a83efaa3b1417f9e787c", - "dev": true, - "requires": { - "gift": "0.10.2", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "vinyl-fs": "2.4.4", - "wrap-promise": "1.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - } - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "3.5.3", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "object-assign": "4.1.1", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - } - } - } - }, - "gulp-jshint": { - "version": "https://registry.npmjs.org/gulp-jshint/-/gulp-jshint-2.0.4.tgz", - "integrity": "sha1-84KxhWSxBy3vDJqvdTwUba208Og=", - "dev": true, - "requires": { - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "rcloader": "https://registry.npmjs.org/rcloader/-/rcloader-0.2.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } - }, - "gulp-json-editor": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.2.2.tgz", - "integrity": "sha512-4Om5cpjmmB6Nj2OlpRvh8TbMgIWz/OivYpvGR+iki8iQs45iuNUrvFi/ao+niQIe7sIJLWuoMkJmc3rCVvuS3Q==", - "dev": true, - "requires": { - "deepmerge": "2.1.0", - "detect-indent": "5.0.0", - "js-beautify": "1.7.5", - "plugin-error": "1.0.1", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } - }, - "gulp-less": { - "version": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.3.2.tgz", - "integrity": "sha1-9mNq3MZhUKiQJxn6WZY/x/hipJo=", - "dev": true, - "requires": { - "accord": "https://registry.npmjs.org/accord/-/accord-0.27.3.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "less": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" - }, - "dependencies": { - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, - "gulp-ng-annotate": { - "version": "https://registry.npmjs.org/gulp-ng-annotate/-/gulp-ng-annotate-2.0.0.tgz", - "integrity": "sha1-hKg9sfAWUgvXD5pc+p8/6J4logU=", - "dev": true, - "requires": { - "bufferstreams": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.3.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "merge": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "ng-annotate": "https://registry.npmjs.org/ng-annotate/-/ng-annotate-1.2.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" - } - }, - "gulp-ng-config": { - "version": "https://registry.npmjs.org/gulp-ng-config/-/gulp-ng-config-1.5.0.tgz", - "integrity": "sha1-s4++hBzi0mdOxz2LZdpXXlgsuDE=", - "dev": true, - "requires": { - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "js-yaml": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" - } - }, - "gulp-preprocess": { - "version": "https://registry.npmjs.org/gulp-preprocess/-/gulp-preprocess-2.0.0.tgz", - "integrity": "sha1-Bnv2pOG3A9e0XtIEfOfofVl00kE=", - "dev": true, - "requires": { - "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "preprocess": "https://registry.npmjs.org/preprocess/-/preprocess-3.1.0.tgz" - }, - "dependencies": { - "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } - } - }, - "gulp-rename": { - "version": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl": "1.2.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" - } - } - } - }, - "gulp-uglify": { - "version": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.0.tgz", - "integrity": "sha1-DfAzHXKg0wLj434QlIXd3zPG0co=", - "dev": true, - "requires": { - "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "make-error-cause": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.2.tgz", - "vinyl-sourcemaps-apply": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" - }, - "dependencies": { - "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", - "dev": true - }, - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - }, - "uglify-js": { - "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.2.tgz", - "integrity": "sha1-UXryCq16vhXh5MmqM8DMcqoBB6s=", - "dev": true, - "requires": { - "commander": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - } - } - } - }, - "gulp-util": { - "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "beeper": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz" - } - }, - "gulplog": { - "version": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz" - } - }, - "har-schema": { - "version": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true, - "optional": true - }, "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "dev": true, - "optional": true, "requires": { - "ajv": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "har-schema": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz" + "chalk": "1.1.3", + "commander": "2.15.1", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" } }, "has": { - "version": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "function-bind": "1.1.1" } }, "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + "ansi-regex": "2.1.1" } }, "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "has-gulplog": { - "version": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" - } + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true }, - "has-require": { - "version": "https://registry.npmjs.org/has-require/-/has-require-1.2.2.tgz", - "integrity": "sha1-khZ1qxMNvZdo/I2o8ajiQt+kF3Q=", - "dev": true, - "requires": { - "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - } + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true }, "has-value": { - "version": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "has-values": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "has-values": { - "version": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "is-buffer": "1.1.6" } } } }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "is-buffer": "1.1.6" } } } }, "hash-base": { - "version": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "inherits": "2.0.3", + "safe-buffer": "5.1.2" } }, "hash.js": { - "version": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha1-NA3tvmKQGHFRweodd3o0SJNd+EY=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" } }, "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, - "optional": true, "requires": { - "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "sntp": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "hmac-drbg": { - "version": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "minimalistic-assert": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "minimalistic-crypto-utils": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" } }, "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, - "homedir-polyfill": { - "version": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" - } - }, "hosted-git-info": { - "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, - "htmlescape": { - "version": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "html-comment-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", + "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", "dev": true }, - "htmlparser2": { - "version": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "html-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", + "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", "dev": true, "requires": { - "domelementtype": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "domhandler": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "domutils": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "entities": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + "es6-templates": "0.2.3", + "fastparse": "1.1.1", + "html-minifier": "3.5.16", + "loader-utils": "1.1.0", + "object-assign": "4.1.1" + } + }, + "html-minifier": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.16.tgz", + "integrity": "sha512-zP5EfLSpiLRp0aAgud4CQXPQZm9kXwWjR/cF0PfdOj+jjWnOaCgeZcll4kYXSvIBPeUMmyaSc7mM4IDtA+kboA==", + "dev": true, + "requires": { + "camel-case": "3.0.0", + "clean-css": "4.1.11", + "commander": "2.15.1", + "he": "1.1.1", + "param-case": "2.1.1", + "relateurl": "0.2.7", + "uglify-js": "3.3.28" + } + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "3.5.16", + "loader-utils": "0.2.17", + "lodash": "4.17.10", + "pretty-error": "2.1.1", + "tapable": "1.0.0", + "toposort": "1.0.7", + "util.promisify": "1.0.0" }, "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", "dev": true, "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" } - } - } - }, - "http-errors": { - "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - } - }, - "http-parser-js": { - "version": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", - "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=", - "dev": true - }, - "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz" - } - }, - "https-browserify": { - "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", - "dev": true - }, - "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz", - "integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4=", - "dev": true - }, - "ieee754": { - "version": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", - "dev": true - }, - "image-size": { - "version": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true - }, - "indent-string": { - "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" - } - }, - "indexof": { - "version": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "indx": { - "version": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", - "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", - "dev": true - }, - "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - } - }, - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", - "dev": true - }, - "inline-source-map": { - "version": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", - "dev": true, - "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - } - }, - "insert-module-globals": { - "version": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", - "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "combine-source-map": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "lexical-scope": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "interpret": { - "version": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invert-kv": { - "version": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", - "dev": true, - "requires": { - "is-relative": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "is-windows": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz" - } - }, - "is-accessor-descriptor": { - "version": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-arrayish": { - "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz" - } - }, - "is-buffer": { - "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", - "dev": true - }, - "is-builtin-module": { - "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" - } - }, - "is-data-descriptor": { - "version": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } - }, - "is-defined": { - "version": "https://registry.npmjs.org/is-defined/-/is-defined-1.0.0.tgz", - "integrity": "sha1-HwfKZ9Vx9ZTEsUQVpF9774j5K/U=", - "dev": true - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.1.tgz", - "integrity": "sha1-LGAjWZveLenV0si5qdlAggNrbvI=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true } } }, - "is-dotfile": { - "version": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "htmlparser2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", "dev": true, "requires": { - "is-primitive": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" - } - }, - "is-extendable": { - "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - } - }, - "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - } - }, - "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - } - }, - "is-integer": { - "version": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz", - "integrity": "sha1-a96Bqs3feLZZtmKdYpytxRqIbVw=", - "dev": true, - "requires": { - "is-finite": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz" - } - }, - "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "is-obj": { - "version": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-odd": { - "version": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", - "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", - "dev": true, - "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + "domelementtype": "1.3.0", + "domhandler": "2.1.0", + "domutils": "1.1.6", + "readable-stream": "1.0.34" }, "dependencies": { - "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "domutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", "dev": true, "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "domelementtype": "1.3.0" } }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "http-assert": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.3.0.tgz", + "integrity": "sha1-oxpc+IyHPsu1eWkH1NbxMujAHko=", + "dev": true, + "requires": { + "deep-equal": "1.0.1", + "http-errors": "1.6.3" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.4.0" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "6.0.22" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "postcss": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" } } } }, - "is-plain-object": { - "version": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "ieee754": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", + "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", + "requires": { + "ansi-escapes": "1.4.0", + "chalk": "1.1.3", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx": "4.1.0", + "string-width": "2.1.1", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-ci": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "dev": true, + "requires": { + "ci-info": "1.1.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "is-posix-bracket": { - "version": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", "dev": true }, "is-primitive": { - "version": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, - "is-relative": { - "version": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "is-unc-path": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz" + "has": "1.0.3" } }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, "is-stream": { - "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "dev": true, + "requires": { + "html-comment-regex": "1.1.1" + } + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", "dev": true }, "is-typedarray": { - "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true, - "optional": true - }, - "is-unc-path": { - "version": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", - "dev": true, - "requires": { - "unc-path-regex": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz" - } + "dev": true }, "is-utf8": { - "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "is-valid-month": { - "version": "https://registry.npmjs.org/is-valid-month/-/is-valid-month-1.0.0.tgz", - "integrity": "sha1-VgloaRDi2tgOusg/CjSXg0klbJk=", - "dev": true, - "requires": { - "is-integer": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz" - } - }, - "is-windows": { - "version": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", - "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { - "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-2.0.0.tgz", - "integrity": "sha1-II3ocr1zeMKpKvlCij9W65GhIsQ=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "isarray": "1.0.0" } }, "isstream": { - "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true, - "optional": true - }, - "jquery": { - "version": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", - "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=", "dev": true }, - "js-beautify": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.7.5.tgz", - "integrity": "sha512-9OhfAqGOrD7hoQBLJMTA+BKuKmoEtTJXzZ7WDF/9gvjtey1koVLuZqIY6c51aPDjbNdNtIXAkiWKVhziawE9Og==", - "dev": true, - "requires": { - "config-chain": "1.1.11", - "editorconfig": "0.13.3", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "nopt": "3.0.6" - } + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" + }, + "js-base64": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz", + "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true }, "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "esprima": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz" + "argparse": "1.0.10", + "esprima": "2.7.3" } }, "jsbn": { - "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true }, - "jshint": { - "version": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", - "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", - "dev": true, - "requires": { - "cli": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "exit": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "htmlparser2": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "lodash": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "shelljs": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "strip-json-comments": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" - }, - "dependencies": { - "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", - "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=", - "dev": true - } - } + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true }, - "json-loader": { - "version": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=", + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-schema": { - "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true, - "optional": true + "dev": true }, "json-schema-traverse": { - "version": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", - "dev": true, - "requires": { - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } - }, "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "json5": { - "version": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, - "jsonify": { - "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, "jsprim": { - "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, - "optional": true, "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true + "dev": true } } }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E=", "dev": true }, - "labeled-stream-splicer": { - "version": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", - "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "killable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "stream-splicer": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz" + "is-buffer": "1.1.6" } }, - "lazy-async": { - "version": "https://registry.npmjs.org/lazy-async/-/lazy-async-1.0.1.tgz", - "integrity": "sha1-UqKVSmBVexOw0qyR2yYcxjMaphM=", + "koa": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.5.1.tgz", + "integrity": "sha512-cchwbMeG2dv3E2xTAmheDAuvR53tPgJZN/Hf1h7bTzJLSPcFZp8/t5+bNKJ6GaQZoydhZQ+1GNruhKdj3lIrug==", "dev": true, "requires": { - "array-last": "https://registry.npmjs.org/array-last/-/array-last-1.0.2.tgz", - "assert-equal": "https://registry.npmjs.org/assert-equal/-/assert-equal-1.0.0.tgz", - "assert-ok": "https://registry.npmjs.org/assert-ok/-/assert-ok-1.0.0.tgz", - "call-all-fns": "https://registry.npmjs.org/call-all-fns/-/call-all-fns-1.0.1.tgz", - "dezalgo": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "dot-prop": "https://registry.npmjs.org/dot-prop/-/dot-prop-2.4.0.tgz", - "to-array": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" + "accepts": "1.3.5", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookies": "0.7.1", + "debug": "2.6.9", + "delegates": "1.0.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "error-inject": "1.0.0", + "escape-html": "1.0.3", + "fresh": "0.5.2", + "http-assert": "1.3.0", + "http-errors": "1.6.3", + "is-generator-function": "1.0.7", + "koa-compose": "4.1.0", + "koa-convert": "1.2.0", + "koa-is-json": "1.0.0", + "mime-types": "2.1.18", + "on-finished": "2.3.0", + "only": "0.0.2", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "type-is": "1.6.16", + "vary": "1.1.2" + } + }, + "koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true + }, + "koa-convert": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "dev": true, + "requires": { + "co": "4.6.0", + "koa-compose": "3.2.1" }, "dependencies": { - "dot-prop": { - "version": "https://registry.npmjs.org/dot-prop/-/dot-prop-2.4.0.tgz", - "integrity": "sha1-hI4o9/HVB0DGdHqzywdnBGK2+Jw=", + "koa-compose": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", "dev": true, "requires": { - "is-obj": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + "any-promise": "1.3.0" } } } }, - "lazy-cache": { - "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "koa-is-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=", + "dev": true + }, + "koa-webpack": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/koa-webpack/-/koa-webpack-4.0.0.tgz", + "integrity": "sha512-P+j2TzeZAqFwscd/dlLykk/sxwr6wQ5Tp3FYDhqv1+y9aRIffTPnu2zK+1BhfM+Kyh8bepU1jFR420maE+Vajw==", "dev": true, "requires": { - "set-getter": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz" + "app-root-path": "2.0.1", + "merge-options": "1.0.1", + "webpack-dev-middleware": "3.1.3", + "webpack-hot-client": "3.0.0", + "webpack-log": "1.2.0" } }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", "dev": true, "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "package-json": "4.0.1" } }, "lcid": { - "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" + "invert-kv": "1.0.0" } }, - "less": { - "version": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=", - "dev": true, - "requires": { - "errno": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "image-size": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "mime": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "promise": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "request": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - }, - "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true, - "optional": true - } - } - }, - "lexical-scope": { - "version": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", - "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", - "dev": true, - "requires": { - "astw": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz" - } - }, - "liftoff": { - "version": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "findup-sync": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "fined": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "flagged-respawn": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "object.map": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "rechoir": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - } - }, - "livereload-js": { - "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", - "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", + "leb": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/leb/-/leb-0.3.0.tgz", + "integrity": "sha1-Mr7p+tFoMo1q6oUi2DP0GA7tHaM=", "dev": true }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" }, "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true - }, - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } } } }, - "load-script": { - "version": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", - "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=", - "dev": true - }, - "load-script-global": { - "version": "https://registry.npmjs.org/load-script-global/-/load-script-global-1.0.2.tgz", - "integrity": "sha1-WtC2XJS6UZHwmZnaPIab00+hAcM=", - "dev": true, - "requires": { - "assert-ok": "https://registry.npmjs.org/assert-ok/-/assert-ok-1.0.0.tgz", - "cuid": "https://registry.npmjs.org/cuid/-/cuid-1.3.8.tgz", - "dezalgo": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "ear": "https://registry.npmjs.org/ear/-/ear-1.0.1.tgz", - "global": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "load-script": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", - "query-extend": "https://registry.npmjs.org/query-extend/-/query-extend-0.2.0.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, "loader-runner": { - "version": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", "dev": true }, "loader-utils": { - "version": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "emojis-list": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" } }, "locate-path": { - "version": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "path-exists": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - }, - "dependencies": { - "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } + "p-locate": "2.0.0", + "path-exists": "3.0.0" } }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "lodash._basecopy": { - "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._escapehtmlchar": { - "version": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "requires": { - "lodash._htmlescapes": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" - } - }, - "lodash._escapestringchar": { - "version": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", - "dev": true - }, - "lodash._getnative": { - "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._htmlescapes": { - "version": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._isnative": { - "version": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", - "dev": true - }, - "lodash._objecttypes": { - "version": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", - "dev": true - }, - "lodash._reescape": { - "version": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._reunescapedhtml": { - "version": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - }, - "dependencies": { - "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } - } - } - }, - "lodash._root": { - "version": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash._shimkeys": { - "version": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" - } + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, "lodash.assign": { - "version": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true }, - "lodash.clone": { - "version": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, "lodash.clonedeep": { - "version": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, - "lodash.defaults": { - "version": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" - }, - "dependencies": { - "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" - } - } - } - }, - "lodash.escape": { - "version": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz" - } - }, - "lodash.flatten": { - "version": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.isarguments": { - "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isobject": { - "version": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" - } - }, - "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "lodash.isarguments": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" - } - }, "lodash.memoize": { - "version": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, - "lodash.merge": { - "version": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", - "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=", + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", "dev": true }, - "lodash.partialright": { - "version": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", - "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=", + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, - "lodash.pick": { - "version": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "lodash.restparam": { - "version": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.some": { - "version": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "lodash.template": { - "version": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "lodash._basetostring": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "lodash._basevalues": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "lodash.restparam": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz" - } - }, - "lodash.templatesettings": { - "version": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz" - } - }, "lodash.uniq": { - "version": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, - "lodash.values": { - "version": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", - "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz" + "chalk": "2.4.1" }, "dependencies": { - "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "lodash._isnative": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "lodash._shimkeys": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" } } } }, - "longest": { - "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "dev": true, + "requires": { + "es6-symbol": "3.1.1", + "object.assign": "4.1.0" + } + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", "dev": true }, "loud-rejection": { - "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz" + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" } }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "make-error": { - "version": "https://registry.npmjs.org/make-error/-/make-error-1.3.2.tgz", - "integrity": "sha1-h2L/rSRE3Y/x98gZYp+ijiT+ocQ=", - "dev": true - }, - "make-error-cause": { - "version": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "dev": true, "requires": { - "make-error": "https://registry.npmjs.org/make-error/-/make-error-1.3.2.tgz" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, - "make-iterator": { - "version": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", - "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", + "lunr": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.1.6.tgz", + "integrity": "sha512-ydJpB8CX8cZ/VE+KMaYaFcZ6+o2LruM6NG76VXdflYTgluvVemz1lW4anE+pyBbLvxJHZdvD1Jy/fOqdzAEJog==" + }, + "magic-string": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", "dev": true, "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } + "vlq": "0.2.3" } }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-cache": { - "version": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-obj": { - "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, - "map-stream": { - "version": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, "map-visit": { - "version": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" + "object-visit": "1.0.1" } }, + "math-expression-evaluator": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", + "dev": true + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, "md5.js": { - "version": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "dev": true, "requires": { - "hash-base": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "dependencies": { - "hash-base": { - "version": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - } + "hash-base": "3.0.4", + "inherits": "2.0.3" } }, "media-typer": { - "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, "mem": { - "version": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz" + "mimic-fn": "1.2.0" } }, "memory-fs": { - "version": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "errno": "0.1.7", + "readable-stream": "2.3.6" } }, "meow": { - "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "loud-rejection": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "map-obj": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "redent": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "trim-newlines": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" - }, - "dependencies": { - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" } }, - "merge": { - "version": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", - "dev": true - }, - "merge-stream": { - "version": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "merge-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz", + "integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==", "dev": true, "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "is-plain-obj": "1.1.0" } }, - "method-override": { - "version": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", - "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", - "dev": true, - "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "methods": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "vary": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - }, - "dependencies": { - "vary": { - "version": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - } - } - }, - "methods": { - "version": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, "micromatch": { - "version": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.4.tgz", - "integrity": "sha1-u4EudBpB+YLIVOQrQhp+rEWHlvQ=", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "braces": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "extglob": "https://registry.npmjs.org/extglob/-/extglob-2.0.3.tgz", - "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "nanomatch": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.6.tgz", - "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "regex-not": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "miller-rabin": { - "version": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "brorand": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + "bn.js": "4.11.8", + "brorand": "1.1.0" } }, - "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, "mime-db": { - "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", "dev": true }, "mime-types": { - "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz" + "mime-db": "1.33.0" } }, "mimic-fn": { - "version": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", - "dev": true - }, - "min-document": { - "version": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "requires": { - "dom-walk": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "minimalistic-assert": { - "version": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { - "version": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" + "brace-expansion": "1.1.11" } }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, - "mixin-deep": { - "version": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", - "integrity": "sha1-R6hzK6l3mUV8jB7KKPlRMtfoFQo=", + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, "requires": { - "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" + "arrify": "1.0.1", + "is-plain-obj": "1.1.0" + } + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { - "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "is-plain-object": "2.0.4" } } } }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "0.1.8", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + "minimist": "0.0.8" }, "dependencies": { "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } } }, - "module-deps": { - "version": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", - "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", - "dev": true, - "requires": { - "JSONStream": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "browser-resolve": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "cached-path-relative": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", - "concat-stream": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", - "defined": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "detective": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "parents": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "stream-combiner2": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "subarg": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "mousetrap": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.1.tgz", + "integrity": "sha1-KghfXHUSlMdefoH27CVFspy/Qtk=" }, - "morgan": { - "version": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", - "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "basic-auth": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" } }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "multiparty": { - "version": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", - "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "stream-counter": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz" - }, - "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - } - } + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, - "multipipe": { - "version": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, "requires": { - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz" - }, - "dependencies": { - "duplexer2": { - "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - } + "any-promise": "1.3.0", + "object-assign": "4.1.1", + "thenify-all": "1.6.0" } }, "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true + }, + "nanoassert": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", + "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=", + "dev": true + }, + "nanobus": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/nanobus/-/nanobus-4.3.3.tgz", + "integrity": "sha512-4/uzl+LkMGoVv/9eMzH2QFvefmlJErT0KR7EmuYbmht2QvxSEqTjhFFOZ/KHE6chH58fKL3njrOcEwbYV0h9Yw==", "dev": true, - "optional": true + "requires": { + "nanotiming": "7.3.1", + "remove-array-items": "1.0.0" + } }, "nanomatch": { - "version": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.6.tgz", - "integrity": "sha1-8nIz6Xw0qHBrfngaS8YRyVeoFiU=", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "dev": true, "requires": { - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "fragment-cache": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "is-odd": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "regex-not": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "snapdragon": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "to-regex": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, - "natives": { - "version": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha1-ARrM4ffL2H97prMJPWzZOSvhxXQ=", - "dev": true + "nanoscheduler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nanoscheduler/-/nanoscheduler-1.0.3.tgz", + "integrity": "sha512-jBbrF3qdU9321r8n9X7yu18DjP31Do2ItJm3mWrt90wJTrnDO+HXpoV7ftaUglAtjgj9s+OaCxGufbvx6pvbEQ==", + "dev": true, + "requires": { + "nanoassert": "1.1.0" + } + }, + "nanotiming": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/nanotiming/-/nanotiming-7.3.1.tgz", + "integrity": "sha512-l3lC7v/PfOuRWQa8vV29Jo6TG10wHtnthLElFXs4Te4Aas57Fo4n1Q8LH9n+NDh9riOzTVvb2QNBhTS4JUKNjw==", + "dev": true, + "requires": { + "nanoassert": "1.1.0", + "nanoscheduler": "1.0.3" + } }, "negotiator": { - "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", - "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, - "ng-annotate": { - "version": "https://registry.npmjs.org/ng-annotate/-/ng-annotate-1.2.2.tgz", - "integrity": "sha1-3D/FG6Cy+LOF2+BH9NoG9YCh/WE=", - "dev": true, + "neo-async": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", + "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "ngx-infinite-scroll": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-0.8.4.tgz", + "integrity": "sha512-pXNYQiOKONOEQZeHAbUoyB0cru7e57B6fEW1hRd+pUKSNpzj3jM67Xww7rMEIl+ESgJvW7dJ72iR8S7F7YludQ==", "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-2.6.4.tgz", - "alter": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", - "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "optimist": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "ordered-ast-traverse": "https://registry.npmjs.org/ordered-ast-traverse/-/ordered-ast-traverse-1.1.1.tgz", - "simple-fmt": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", - "simple-is": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "stable": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz", - "stringmap": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", - "stringset": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz", - "tryor": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz" - }, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-2.6.4.tgz", - "integrity": "sha1-6x9FtKQ/ox0DcBpexG87Umc+kO4=", - "dev": true - } + "opencollective": "1.0.3" } }, - "ngclipboard": { - "version": "https://registry.npmjs.org/ngclipboard/-/ngclipboard-1.1.2.tgz", - "integrity": "sha1-RZ8B8+4eisQBWZquo3uXdQh9WW0=", + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { - "clipboard": "https://registry.npmjs.org/clipboard/-/clipboard-1.5.16.tgz" - }, - "dependencies": { - "clipboard": { - "version": "https://registry.npmjs.org/clipboard/-/clipboard-1.5.16.tgz", - "integrity": "sha1-kW1ec5sAZL5hsLSKU1cx7K7z02c=", - "dev": true, - "requires": { - "good-listener": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "select": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "tiny-emitter": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.2.0.tgz" - } - }, - "tiny-emitter": { - "version": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.2.0.tgz", - "integrity": "sha1-bchFBSywjr78GHRyO1jySmSMO28=", - "dev": true - } + "lower-case": "1.1.4" } }, - "ngstorage": { - "version": "https://registry.npmjs.org/ngstorage/-/ngstorage-0.3.11.tgz", - "integrity": "sha1-FjfEW4ctkJ2cx+GLN0iY1QsuhE8=", - "dev": true - }, - "node-fingerprint": { - "version": "https://registry.npmjs.org/node-fingerprint/-/node-fingerprint-0.0.2.tgz", - "integrity": "sha1-Mcur63GmeufdWn3AQuUcPHWGhQE=", - "dev": true + "node-fetch": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } }, "node-forge": { - "version": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", - "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", - "dev": true + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" }, - "node-libs-browser": { - "version": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", + "node-gyp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", + "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", "dev": true, "requires": { - "assert": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", - "browserify-zlib": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "buffer": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "console-browserify": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "constants-browserify": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "crypto-browserify": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "domain-browser": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "events": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "https-browserify": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "os-browserify": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "path-browserify": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "querystring-es3": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "stream-browserify": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "stream-http": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "timers-browserify": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", - "tty-browserify": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "url": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "util": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "vm-browserify": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz" + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.79.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.1" }, "dependencies": { - "browserify-zlib": { - "version": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.6", + "stream-browserify": "2.0.1", + "stream-http": "2.8.3", + "string_decoder": "1.1.1", + "timers-browserify": "2.0.10", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.4", + "vm-browserify": "0.0.4" + } + }, + "node-sass": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz", + "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==", + "dev": true, + "requires": { + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.3", + "get-stdin": "4.0.1", + "glob": "7.1.2", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "lodash.mergewith": "4.6.1", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.10.0", + "node-gyp": "3.6.2", + "npmlog": "4.1.2", + "request": "2.79.0", + "sass-graph": "2.2.4", + "stdout-stream": "1.4.0", + "true-case-path": "1.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", "dev": true, "requires": { - "pako": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz" - } - }, - "https-browserify": { - "version": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "os-browserify": { - "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "pako": { - "version": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } - }, - "timers-browserify": { - "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", - "integrity": "sha1-lspT9LeUpefA4b18yIo3Ipj6AeY=", - "dev": true, - "requires": { - "setimmediate": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + "lru-cache": "4.1.3", + "which": "1.3.1" } } } @@ -6552,393 +5617,403 @@ } }, "normalize-package-data": { - "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "is-builtin-module": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "semver": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "validate-npm-package-license": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz" + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" } }, "normalize-path": { - "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" } }, "npm-run-path": { - "version": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" + "path-key": "2.0.1" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true - }, - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "object-copy": { - "version": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true - } - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "is-descriptor": "0.1.6" } } } }, "object-keys": { - "version": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", "dev": true }, "object-visit": { - "version": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "isobject": "3.0.1" }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, - "object.defaults": { - "version": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "array-each": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - }, - "dependencies": { - "array-slice": { - "version": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", - "dev": true - }, - "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" } }, - "object.map": { - "version": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { - "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "make-iterator": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz" + "define-properties": "1.1.2", + "es-abstract": "1.12.0" } }, "object.omit": { - "version": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - }, - "dependencies": { - "for-own": { - "version": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" - } - } + "for-own": "0.1.5", + "is-extendable": "0.1.1" } }, "object.pick": { - "version": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "isobject": "3.0.1" }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "on-finished": { - "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "requires": { - "ee-first": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "ee-first": "1.1.1" } }, - "on-headers": { - "version": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "wrappy": "1.0.2" } }, - "optimist": { - "version": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" - }, - "dependencies": { - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - } + "mimic-fn": "1.2.0" } }, - "orchestrator": { - "version": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "sequencify": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "stream-consume": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" - } - }, - "ordered-ast-traverse": { - "version": "https://registry.npmjs.org/ordered-ast-traverse/-/ordered-ast-traverse-1.1.1.tgz", - "integrity": "sha1-aEOhcLwO7otSDMjdwd3TqjD6BXw=", - "dev": true, - "requires": { - "ordered-esprima-props": "https://registry.npmjs.org/ordered-esprima-props/-/ordered-esprima-props-1.1.0.tgz" - } - }, - "ordered-esprima-props": { - "version": "https://registry.npmjs.org/ordered-esprima-props/-/ordered-esprima-props-1.1.0.tgz", - "integrity": "sha1-qYJwht9fAQqmDpvQK24DNc6i/8s=", + "only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", "dev": true }, - "ordered-read-streams": { - "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.0.6", + "minimist": "1.2.0", + "node-fetch": "1.6.3", + "opn": "4.0.2" + } + }, + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } }, "os-browserify": { - "version": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", - "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, "os-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "p-finally": { - "version": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-limit": { - "version": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } }, "p-locate": { - "version": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz" + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" } }, "pako": { - "version": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", "dev": true }, "papaparse": { - "version": "https://registry.npmjs.org/papaparse/-/papaparse-4.3.6.tgz", - "integrity": "sha1-lWbtoOyrE6/LdApiOBxpn0hssUU=", - "dev": true + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-4.3.5.tgz", + "integrity": "sha1-ts31yub+nsYDsb5m8RSmOsZFoDY=" }, - "parents": { - "version": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "requires": { - "path-platform": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz" + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "2.3.2" } }, "parse-asn1": { - "version": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "dev": true, "requires": { - "asn1.js": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", - "browserify-aes": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "evp_bytestokey": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "pbkdf2": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz" - } - }, - "parse-filepath": { - "version": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "path-root": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz" + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" } }, "parse-glob": { - "version": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "is-dotfile": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - }, - "dependencies": { - "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } - } - } - }, - "parse-int": { - "version": "https://registry.npmjs.org/parse-int/-/parse-int-1.0.2.tgz", - "integrity": "sha1-QzYNYNjuNaEll4DgUisLlqhOb8E=", - "dev": true, - "requires": { - "is-integer": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" } }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" - } - }, - "parse-passwd": { - "version": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-year": { - "version": "https://registry.npmjs.org/parse-year/-/parse-year-1.0.0.tgz", - "integrity": "sha1-XB+Hh7Z8xY2uqHuKgDLu4uQtOIs=", - "dev": true, - "requires": { - "expand-year": "https://registry.npmjs.org/expand-year/-/expand-year-1.0.0.tgz", - "parse-int": "https://registry.npmjs.org/parse-int/-/parse-int-1.0.2.tgz" + "error-ex": "1.3.1" } }, "parseurl": { - "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, "pascalcase": { - "version": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "patch-text": { - "version": "https://registry.npmjs.org/patch-text/-/patch-text-1.0.2.tgz", - "integrity": "sha1-S/NuZeUXM9bpjwz2LgkDTaoDSKw=", - "dev": true - }, "path-browserify": { - "version": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -6949,1193 +6024,1914 @@ "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true }, "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { - "version": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { - "version": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, - "path-platform": { - "version": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", - "dev": true - }, - "path-root": { - "version": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz" - } - }, - "path-root-regex": { - "version": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - }, - "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } - }, - "pause": { - "version": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", - "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=", - "dev": true - }, - "pause-stream": { - "version": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + "pify": "3.0.0" } }, "pbkdf2": { - "version": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha1-o14TxkeZsGzhUyD0WcIw5o5zut4=", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", "dev": true, "requires": { - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "create-hmac": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "ripemd160": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz" + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" } }, - "performance-now": { - "version": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true, - "optional": true - }, - "pff": { - "version": "https://registry.npmjs.org/pff/-/pff-1.0.0.tgz", - "integrity": "sha1-6l8J7mVxyuKSp4/CgJBaOGVmjng=", - "dev": true - }, "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "pinkie": { - "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { - "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { - "pinkie": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + "pinkie": "2.0.4" } }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "ansi-colors": "1.1.0", - "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "extend-shallow": "3.0.2" + "find-up": "2.1.0" + } + }, + "popper.js": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.3.tgz", + "integrity": "sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU=" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.5", + "source-map": "0.5.7", + "supports-color": "3.2.3" }, "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "is-extendable": "1.0.1" - } + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "has-flag": "1.0.0" } } } }, - "posix-character-classes": { - "version": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "preprocess": { - "version": "https://registry.npmjs.org/preprocess/-/preprocess-3.1.0.tgz", - "integrity": "sha1-pE5c3Vu7WlTwrSiaru2AmV19k4o=", + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "xregexp": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.0.tgz" + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" } }, + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "dev": true, + "requires": { + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "uniqs": "2.0.0" + } + }, + "postcss-filter-plugins": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", + "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "dev": true, + "requires": { + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.2" + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "dev": true + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", + "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", + "dev": true, + "requires": { + "postcss": "6.0.22" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "postcss": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.22" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "postcss": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.22" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "postcss": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.22" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "postcss": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", + "dev": true, + "requires": { + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "dev": true, + "requires": { + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "dev": true, + "requires": { + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "dev": true + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "dev": true, + "requires": { + "has": "1.0.3", + "postcss": "5.2.18", + "uniqs": "2.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, "preserve": { - "version": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, - "pretty-hrtime": { - "version": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "print-value": { - "version": "https://registry.npmjs.org/print-value/-/print-value-1.0.0.tgz", - "integrity": "sha1-VbOjouxNCmElJXBwcAylgsS4634=", + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", "dev": true, "requires": { - "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.0.0.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + "renderkid": "2.0.1", + "utila": "0.4.0" } }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, "process": { - "version": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, - "promise": { - "version": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", - "dev": true, - "optional": true, - "requires": { - "asap": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "promise-polyfill": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz", + "integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc=" + }, "prr": { - "version": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "pseudomap": { - "version": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "public-encrypt": { - "version": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", "dev": true, "requires": { - "bn.js": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "browserify-rsa": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "create-hash": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "parse-asn1": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz" + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" } }, "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", - "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", "dev": true }, - "query-extend": { - "version": "https://registry.npmjs.org/query-extend/-/query-extend-0.2.0.tgz", - "integrity": "sha1-6xL04zytrhRzlrhA/Wi2XDnM+VQ=", - "dev": true + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } }, "querystring": { - "version": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, "querystring-es3": { - "version": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "random-bytes": { - "version": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, "randomatic": { - "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", "dev": true, "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" }, "dependencies": { "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "randombytes": { - "version": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha1-3ACaJGuNCaF3tLegrne8Vw9LG3k=", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "safe-buffer": "5.1.2" } }, "randomfill": { - "version": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", - "integrity": "sha1-uWt99YfwHdkXJsQY8wVTsUGOPWI=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "randombytes": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "randombytes": "2.0.6", + "safe-buffer": "5.1.2" } }, "range-parser": { - "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, - "raw-body": { - "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "unpipe": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "dependencies": { - "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true - }, - "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - } - } - }, - "rcfinder": { - "version": "https://registry.npmjs.org/rcfinder/-/rcfinder-0.1.9.tgz", - "integrity": "sha1-8+gPOH3fmugK4wpBADKWQuroERU=", - "dev": true, - "requires": { - "lodash.clonedeep": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" - } - }, - "rcloader": { - "version": "https://registry.npmjs.org/rcloader/-/rcloader-0.2.2.tgz", - "integrity": "sha1-WNIpi0YtC5v9ITPSoex0+9cFxxc=", - "dev": true, - "requires": { - "lodash.assign": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "lodash.isobject": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "lodash.merge": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", - "rcfinder": "https://registry.npmjs.org/rcfinder/-/rcfinder-0.1.9.tgz" - }, - "dependencies": { - "lodash.isobject": { - "version": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=", - "dev": true - } - } - }, - "read-only-stream": { - "version": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" } }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "find-up": "1.1.2", + "read-pkg": "1.1.0" }, "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" } } } }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, "readdirp": { - "version": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "set-immediate-shim": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "3.1.3", + "private": "0.1.8", + "source-map": "0.5.7" }, "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true } } }, - "rechoir": { - "version": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" - } - }, "redent": { - "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "strip-indent": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" + "indent-string": "2.1.0", + "strip-indent": "1.0.1" } }, - "regex-cache": { - "version": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "is-equal-shallow": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "reduce-function-call": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", + "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "dev": true, + "requires": { + "balanced-match": "0.4.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "reflect-metadata": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", + "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==", + "dev": true + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" } }, "regex-not": { - "version": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", - "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "1.2.8", + "safe-buffer": "5.1.2" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.8" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-array-items": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.0.0.tgz", + "integrity": "sha1-B79CyzMvTPboXq2DteToltIyayE=", + "dev": true + }, "remove-trailing-separator": { - "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, + "renderkid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", + "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-converter": "0.1.4", + "htmlparser2": "3.3.0", + "strip-ansi": "3.0.1", + "utila": "0.3.3" + }, + "dependencies": { + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true + } + } + }, "repeat-element": { - "version": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "dev": true }, "repeat-string": { - "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, "repeating": { - "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz" - } - }, - "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "replace-requires": { - "version": "https://registry.npmjs.org/replace-requires/-/replace-requires-1.0.4.tgz", - "integrity": "sha1-AUtzMLa54lV7cQQ7ZvsCZgw79mc=", - "dev": true, - "requires": { - "detective": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", - "has-require": "https://registry.npmjs.org/has-require/-/has-require-1.2.2.tgz", - "patch-text": "https://registry.npmjs.org/patch-text/-/patch-text-1.0.2.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "is-finite": "1.0.2" } }, "request": { - "version": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "dev": true, - "optional": true, "requires": { - "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "performance-now": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" - }, - "dependencies": { - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true, - "optional": true - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", - "dev": true, - "optional": true - } + "aws-sign2": "0.6.0", + "aws4": "1.7.0", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3", + "uuid": "3.2.1" } }, "require-directory": { - "version": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { - "version": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", "dev": true, "requires": { - "path-parse": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz" + "path-parse": "1.0.5" } }, - "resolve-dir": { - "version": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "global-modules": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz" + "resolve-from": "3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", + "dev": true, + "requires": { + "http-errors": "1.6.3", + "path-is-absolute": "1.0.1" } }, "resolve-url": { - "version": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, - "response-time": { - "version": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", - "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", - "dev": true, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "requires": { - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "on-headers": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "dependencies": { - "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - } + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, - "right-align": { - "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" - } + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + "glob": "7.1.2" }, "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "balanced-match": "1.0.0", + "concat-map": "0.0.1" } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true } } }, "ripemd160": { - "version": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "hash-base": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "hash-base": "3.0.4", + "inherits": "2.0.3" } }, - "rndm": { - "version": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", - "dev": true + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "2.1.0" + } }, - "run-sequence": { - "version": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.0.tgz", - "integrity": "sha1-s/jUKDbbidCLL+cE6vDJPf2DNeI=", + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { - "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz" + "aproba": "1.2.0" + } + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + }, + "rxjs": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", + "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==", + "requires": { + "symbol-observable": "1.0.1" } }, "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "select": { - "version": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.10", + "scss-tokenizer": "0.2.3", + "yargs": "7.1.0" + } + }, + "sass-loader": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.0.2.tgz", + "integrity": "sha512-HfoUBjcBf56u7+Qb6/15OmfL4nymtACwAYXRuhgaSUJI3QF0ndID76SiTlwxDYgNYLtvP5s3xVSYMZISezsuKQ==", + "dev": true, + "requires": { + "clone-deep": "2.0.2", + "loader-utils": "1.1.0", + "lodash.tail": "4.1.1", + "neo-async": "2.5.1", + "pify": "3.0.0" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "dev": true, + "requires": { + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "2.4.5", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, - "send": { - "version": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", - "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", "dev": true, "requires": { - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "destroy": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "etag": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "mime": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "range-parser": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", - "statuses": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "statuses": { - "version": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", - "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", - "dev": true - } + "semver": "5.5.0" } }, - "sequencify": { - "version": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "serialize-javascript": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", "dev": true }, - "serve-favicon": { - "version": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", - "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", - "dev": true, - "requires": { - "etag": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "fresh": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" - }, - "dependencies": { - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "serve-index": { - "version": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", - "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", - "dev": true, - "requires": { - "accepts": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", - "batch": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz" - }, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "serve-static": { - "version": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", - "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", - "dev": true, - "requires": { - "escape-html": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "send": "https://registry.npmjs.org/send/-/send-0.13.2.tgz" - } - }, "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-getter": { - "version": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", - "dev": true, - "requires": { - "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" - } - }, "set-immediate-shim": { - "version": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, "set-value": { - "version": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "split-string": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "setimmediate": { - "version": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, "sha.js": { - "version": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", - "integrity": "sha1-mPZIgEdLdPSji42p08Dy0QRjPn0=", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "inherits": "2.0.3", + "safe-buffer": "5.1.2" } }, - "shasum": { - "version": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", "dev": true, "requires": { - "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "sha.js": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz" - } - }, - "shebang-command": { - "version": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" - } - }, - "shebang-regex": { - "version": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shell-quote": { - "version": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "array-map": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "array-reduce": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" - } - }, - "shelljs": { - "version": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true - }, - "sigmund": { - "version": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "simple-fmt": { - "version": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", - "integrity": "sha1-GRv1ZqWeZTBILLJatTtKjchcOms=", - "dev": true - }, - "simple-format": { - "version": "https://registry.npmjs.org/simple-format/-/simple-format-1.0.0.tgz", - "integrity": "sha1-SxIQc1tzZVnEErz1LZdKaLaJxA4=", - "dev": true, - "requires": { - "pff": "https://registry.npmjs.org/pff/-/pff-1.0.0.tgz", - "to-array": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" - } - }, - "simple-is": { - "version": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", - "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=", - "dev": true - }, - "snapdragon": { - "version": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", - "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", - "dev": true, - "requires": { - "base": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "source-map-resolve": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "use": "https://registry.npmjs.org/use/-/use-2.0.2.tgz" + "is-extendable": "0.1.1", + "kind-of": "5.1.0", + "mixin-object": "2.0.1" }, "dependencies": { - "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } - }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, - "snapdragon-node": { - "version": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "define-property": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "snapdragon-util": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.0" }, "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "snapdragon-util": { - "version": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - } - } + "kind-of": "3.2.2" } }, "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, - "optional": true, "requires": { - "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + "hoek": "2.16.3" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "1.1.0" } }, "source-list-map": { - "version": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { - "version": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "decode-uri-component": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "resolve-url": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "source-map-url": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "urix": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" } }, "source-map-url": { - "version": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "sparkles": { - "version": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, "spdx-correct": { - "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-license-ids": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, "spdx-expression-parse": { - "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true - }, - "spdx-license-ids": { - "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", - "dev": true - }, - "split": { - "version": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" } }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, "split-string": { - "version": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" - }, - "dependencies": { - "extend-shallow": { - "version": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" - } - }, - "is-extendable": { - "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", - "dev": true, - "requires": { - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" - } - } + "extend-shallow": "3.0.2" } }, "sprintf-js": { - "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "sshpk": { - "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, - "optional": true, "requires": { - "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "bcrypt-pbkdf": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "dashdash": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "ecc-jsbn": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "getpass": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" }, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "stable": { - "version": "https://registry.npmjs.org/stable/-/stable-0.1.6.tgz", - "integrity": "sha1-kQ9dKu17Ugxud3SZwfMuE5/eyxA=", - "dev": true - }, - "static-extend": { - "version": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "object-copy": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" - }, - "dependencies": { - "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - } - }, - "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", - "dev": true, - "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - } - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } }, - "statuses": { - "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - }, - "stream-browserify": { - "version": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", "dev": true, "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + "safe-buffer": "5.1.2" } }, - "stream-combiner": { - "version": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" - } - }, - "stream-combiner2": { - "version": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } - }, - "stream-consume": { - "version": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", - "dev": true - }, - "stream-counter": { - "version": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", - "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "is-descriptor": "0.1.6" } } } }, - "stream-http": { - "version": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha1-QKBQ7I3DtTsz2ZCUFcAsC/Gr+60=", + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + }, + "stdout-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", + "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", "dev": true, "requires": { - "builtin-status-codes": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "to-arraybuffer": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "readable-stream": "2.3.6" + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "stream-each": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" } }, "stream-shift": { @@ -8144,1326 +7940,2758 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "stream-splicer": { - "version": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", - "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" - } + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "requires": { - "code-point-at": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - } - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "stringmap": { - "version": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", - "integrity": "sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE=", - "dev": true - }, - "stringset": { - "version": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz", - "integrity": "sha1-7yWcTjSTRDd/zRyRPdLoSMnAQrU=", - "dev": true - }, - "stringstream": { - "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true, - "optional": true - }, - "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - } - }, - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "strip-bom": "2.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "requires": { - "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + "ansi-regex": "3.0.0" } } } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, "strip-eof": { - "version": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-indent": { - "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" + "get-stdin": "4.0.1" } }, "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, - "stripe-as-promised": { - "version": "https://registry.npmjs.org/stripe-as-promised/-/stripe-as-promised-2.1.1.tgz", - "integrity": "sha1-kWBAdmMEIepHiPKJWCf2r558DIU=", + "style-loader": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz", + "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==", "dev": true, "requires": { - "dot-prop": "https://registry.npmjs.org/dot-prop/-/dot-prop-2.1.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "stripe-errback": "https://registry.npmjs.org/stripe-errback/-/stripe-errback-1.0.2.tgz" + "loader-utils": "1.1.0", + "schema-utils": "0.4.5" }, "dependencies": { - "dot-prop": { - "version": "https://registry.npmjs.org/dot-prop/-/dot-prop-2.1.0.tgz", - "integrity": "sha1-a9GZ2AeS0jI6K364F19LMtdqfnI=", + "ajv": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", + "dev": true, + "requires": { + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "dev": true, + "requires": { + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" + } } } }, - "stripe-errback": { - "version": "https://registry.npmjs.org/stripe-errback/-/stripe-errback-1.0.2.tgz", - "integrity": "sha1-fR390hvEUKHKrNSKficEJ7+DyNY=", - "dev": true, - "requires": { - "dot-prop": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "subarg": { - "version": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" - } - }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, - "syntax-error": { - "version": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", - "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz" + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" } }, + "sweetalert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.0.tgz", + "integrity": "sha512-9YKj0SvjKyBfRWco50UOsIbXVeifYbxzT9Qda7EsqC01eafHGCSG0IR7g942ufjzt7lnwO8ZZBwr6emXv2fQrg==", + "requires": { + "es6-object-assign": "1.1.0", + "promise-polyfill": "6.1.0" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, "tapable": { - "version": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", "dev": true }, - "temp-write": { - "version": "https://registry.npmjs.org/temp-write/-/temp-write-0.1.1.tgz", - "integrity": "sha1-C2Rng43Xf79/YqDJPah5cy/9qTI=", + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", - "tempfile": "https://registry.npmjs.org/tempfile/-/tempfile-0.1.3.tgz" - }, - "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", - "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", - "dev": true - } + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" } }, - "tempfile": { - "version": "https://registry.npmjs.org/tempfile/-/tempfile-0.1.3.tgz", - "integrity": "sha1-fWtxAEcznTn4RzJ6BW2t8YMQMBA=", + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", "dev": true, "requires": { - "uuid": "https://registry.npmjs.org/uuid/-/uuid-1.4.2.tgz" + "execa": "0.7.0" } }, - "ternary": { - "version": "https://registry.npmjs.org/ternary/-/ternary-1.0.0.tgz", - "integrity": "sha1-RXAnJWCMlJnUapYQ6bDkn/JveJ4=", + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "dev": true, + "requires": { + "any-promise": "1.3.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": "3.3.0" + } + }, "through": { - "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "readable-stream": "2.3.6", + "xtend": "4.0.1" } }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } + "time-fix-plugin": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/time-fix-plugin/-/time-fix-plugin-2.0.3.tgz", + "integrity": "sha512-5StGdiXCiBsq2+RdBQ0NrunFeKqVX0f2Myn8s1YqOxRS+kmuiHcdpPm27ucbM6FYawBKGTOOYxPnqxIBZyiqEg==", + "dev": true }, - "tildify": { - "version": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" - } - }, - "time-stamp": { - "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", "dev": true }, "timers-browserify": { - "version": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "process": "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + "setimmediate": "1.0.5" } }, - "tiny-emitter": { - "version": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", - "integrity": "sha1-gtJ0aKylrejl/R5tIrV91D69+3w=", + "tldjs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tldjs/-/tldjs-2.0.0.tgz", + "integrity": "sha1-gdo/0/HbRnbKkoIGp8XFX0E2kKU=", + "requires": { + "punycode": "1.4.1" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "tiny-lr": { - "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", - "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "body-parser": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "faye-websocket": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "livereload-js": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" }, "dependencies": { - "body-parser": { - "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "bytes": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "content-type": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "http-errors": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "on-finished": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "qs": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "raw-body": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "type-is": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" + "kind-of": "3.2.2" + } + } + } + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", + "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", + "dev": true, + "requires": { + "glob": "6.0.4" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "ts-loader": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.3.1.tgz", + "integrity": "sha512-ra304bebnyxd9nIJoKjQoeQLOENqrDG7vfppS+DkCnqOEv29GuiiWMvgebuCqFko0AkMFpoubRLeFM7YmlkL3w==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "enhanced-resolve": "4.0.0", + "loader-utils": "1.1.0", + "micromatch": "3.1.10", + "semver": "5.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", - "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "enhanced-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", + "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, - "bytes": { - "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", - "dev": true - }, - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, - "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", - "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", - "dev": true - } - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" - } - }, - "to-array": { - "version": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-camel-case": { - "version": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", - "integrity": "sha1-GlYFSy+daWKYzmamCJcyK29CPkY=", - "dev": true, - "requires": { - "to-space-case": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz" - } - }, - "to-no-case": { - "version": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", - "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=", - "dev": true - }, - "to-object-path": { - "version": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - }, - "dependencies": { - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } - } - } - }, - "to-regex": { - "version": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", - "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", - "dev": true, - "requires": { - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "regex-not": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz" - }, - "dependencies": { - "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" } }, "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true } } }, - "to-regex-range": { - "version": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "tsickle": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.26.0.tgz", + "integrity": "sha512-eWJ2CUfttGK0LqF9iJ/Avnxbj4M+fCyJ50Zag3wm73Fut1hsasPRHKxKdrMWVj4BMHnQNx7TO+DdNmLmJTSuNw==", "dev": true, "requires": { - "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map": "0.5.7", + "source-map-support": "0.4.18" + } + }, + "tslib": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz", + "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==" + }, + "tslint": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz", + "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "builtin-modules": "1.1.1", + "chalk": "2.4.1", + "commander": "2.15.1", + "diff": "3.5.0", + "glob": "7.1.2", + "js-yaml": "3.7.0", + "minimatch": "3.0.4", + "resolve": "1.7.1", + "semver": "5.5.0", + "tslib": "1.9.2", + "tsutils": "2.27.1" }, "dependencies": { - "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "color-convert": "1.9.1" } }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" } } } }, - "to-space-case": { - "version": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", - "integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=", + "tslint-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tslint-loader/-/tslint-loader-3.6.0.tgz", + "integrity": "sha512-Me9Qf/87BOfCY8uJJw+J7VMF4U8WiMXKLhKKKugMydF0xMhMOt9wo2mjYTNhwbF9H7SHh8PAIwRG8roisTNekQ==", "dev": true, "requires": { - "to-no-case": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz" + "loader-utils": "1.1.0", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "rimraf": "2.6.2", + "semver": "5.5.0" } }, - "tough-cookie": { - "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", - "dev": true, - "optional": true, - "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" - } - }, - "transformify": { - "version": "https://registry.npmjs.org/transformify/-/transformify-0.1.2.tgz", - "integrity": "sha1-mk9CoVRDPdcnuAV1Qoo8nlSJ6/E=", + "tsutils": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.27.1.tgz", + "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==", "dev": true, "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" - }, - "dependencies": { - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - } + "tslib": "1.9.2" } }, - "trim-newlines": { - "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "tryor": { - "version": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz", - "integrity": "sha1-gUXkynyv9ArN48z5Rui4u3W0Fys=", - "dev": true - }, - "tsscmp": { - "version": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "dev": true - }, "tty-browserify": { - "version": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" - } + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true }, "tweetnacl": { - "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true }, "type-is": { - "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "dev": true, "requires": { - "media-typer": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + "media-typer": "0.3.0", + "mime-types": "2.1.18" } }, "typedarray": { - "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.1.tgz", + "integrity": "sha512-h6pM2f/GDchCFlldnriOhs1QHuwbnmj6/v7499eMHqPeW4V2G0elua2eIc2nu8v2NdHV0Gm+tzX83Hr6nUFjQA==", + "dev": true + }, "uglify-js": { - "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "version": "3.3.28", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz", + "integrity": "sha512-68Rc/aA6cswiaQ5SrE979UJcXX+ADA1z33/ZsPd+fbAiVdjZ16OXdbtGO+rJUUBgK6qdf3SOPhQf3K/ybF5Miw==", "dev": true, "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "uglify-to-browserify": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" + "commander": "2.15.1", + "source-map": "0.6.1" }, "dependencies": { - "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + } + } + }, + "uglifyjs-webpack-plugin": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz", + "integrity": "sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==", + "dev": true, + "requires": { + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "schema-utils": "0.4.5", + "serialize-javascript": "1.5.0", + "source-map": "0.6.1", + "uglify-es": "3.3.9", + "webpack-sources": "1.1.0", + "worker-farm": "1.6.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", "dev": true, "requires": { - "center-align": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "right-align": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.2" } }, - "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "window-size": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "2.13.0", + "source-map": "0.6.1" } } } }, - "uglify-to-browserify": { - "version": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "uglifyjs-webpack-plugin": { - "version": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", - "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", - "dev": true, - "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "uglify-js": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "webpack-sources": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz" - } - }, - "uid-safe": { - "version": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", - "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", - "dev": true, - "requires": { - "random-bytes": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz" - } - }, - "umd": { - "version": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", - "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", - "dev": true - }, - "unc-path-regex": { - "version": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", - "dev": true - }, "union-value": { - "version": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "set-value": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, "set-value": { - "version": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "to-object-path": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } }, - "unique-stream": { - "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, - "unpipe": { - "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", "dev": true }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "dev": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, "unset-value": { - "version": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { - "version": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "has-values": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { - "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "isarray": "1.0.0" } } } }, "has-values": { - "version": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true }, - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true } } }, "urix": { - "version": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, "url": { - "version": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "requires": { - "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "querystring": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + "punycode": "1.3.2", + "querystring": "0.2.0" }, "dependencies": { "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true } } }, - "use": { - "version": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", - "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", + "url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true, "requires": { - "define-property": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "lazy-cache": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" + "prepend-http": "1.0.4" + } + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" }, "dependencies": { - "define-property": { - "version": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "object.getownpropertydescriptors": "2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", + "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", + "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "2.0.3", + "graceful-fs": "4.1.11", + "neo-async": "2.5.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "is-descriptor": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.1.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" } }, "is-descriptor": { - "version": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "is-data-descriptor": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", - "dev": true - } - } - }, - "user-home": { - "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util": { - "version": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "dependencies": { - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-1.4.2.tgz", - "integrity": "sha1-RTAZ9oaWam34PNxSROfJkOzDMvw=", - "dev": true - }, - "v8flags": { - "version": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "validate-npm-package-license": { - "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, - "requires": { - "spdx-correct": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "spdx-expression-parse": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz" - } - }, - "vary": { - "version": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", - "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", - "dev": true - }, - "verror": { - "version": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" - }, - "dependencies": { - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } - }, - "vhost": { - "version": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", - "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=", - "dev": true - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" - } - }, - "vinyl-fs": { - "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "glob-watcher": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" - }, - "dependencies": { - "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } } } }, - "vinyl-source-stream": { - "version": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", - "dev": true, - "requires": { - "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" - }, - "dependencies": { - "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - } - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" - } - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" - } - } - } + "web-animations-js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.1.tgz", + "integrity": "sha1-Om2bwVGWN3qQ+OKAP6UmIWWwRRA=" }, - "vinyl-sourcemaps-apply": { - "version": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - } - }, - "vm-browserify": { - "version": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" - } - }, - "watchpack": { - "version": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", - "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", - "dev": true, - "requires": { - "async": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "chokidar": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" - }, - "dependencies": { - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - } - } + "webcrypto-shim": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.4.tgz", + "integrity": "sha512-I2lnL+K2oPNE9ryVHwo42oDnt8XQ9E1KKMGCmcT7OXaAKPmUeCi/G0nUgLR6M6Ztj05ZCxLMGf5bXNaSo+wURg==" }, "webpack": { - "version": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", - "integrity": "sha1-UpG4dQeM8qv0K90jr+P4+WwX1yU=", + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.10.2.tgz", + "integrity": "sha512-S4yIBevM7DFSAOAvWSBgvuH5mtJ3HgjAS6tCGsTxxHtrVdbntdRVaPey2u9sCns6KV859Vwd2DwkvBLTcs6t6g==", "dev": true, "requires": { - "acorn": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "acorn-dynamic-import": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "ajv": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "ajv-keywords": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "async": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "enhanced-resolve": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "escope": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "json-loader": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "loader-runner": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "loader-utils": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "node-libs-browser": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "tapable": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "uglifyjs-webpack-plugin": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", - "watchpack": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", - "webpack-sources": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "yargs": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz" + "@webassemblyjs/ast": "1.5.9", + "@webassemblyjs/wasm-edit": "1.5.9", + "@webassemblyjs/wasm-opt": "1.5.9", + "@webassemblyjs/wasm-parser": "1.5.9", + "acorn": "5.6.1", + "acorn-dynamic-import": "3.0.0", + "ajv": "6.5.0", + "ajv-keywords": "3.2.0", + "chrome-trace-event": "0.1.3", + "enhanced-resolve": "4.0.0", + "eslint-scope": "3.7.1", + "json-parse-better-errors": "1.0.2", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "micromatch": "3.1.10", + "mkdirp": "0.5.1", + "neo-async": "2.5.1", + "node-libs-browser": "2.1.0", + "schema-utils": "0.4.5", + "tapable": "1.0.0", + "uglifyjs-webpack-plugin": "1.2.5", + "watchpack": "1.6.0", + "webpack-sources": "1.1.0" }, "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha1-dEbTlFnFT7SagObuZHgUm5QOyCI=", - "dev": true - }, "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", "dev": true, "requires": { - "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "fast-deep-equal": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.2" } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "enhanced-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", + "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "dev": true, + "requires": { + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", + "dev": true + } + } + }, + "webpack-cli": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.0.2.tgz", + "integrity": "sha512-XJnOWrGOVnxAa1ry0iL53K2RRhwjndR4x7ePfOJZbXBn0iHXumu9U94ZMssDyIt7I4qdKvyVuuSEjXjeAcAldg==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "enhanced-resolve": "4.0.0", + "global-modules-path": "2.1.0", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "loader-utils": "1.1.0", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.0", + "yargs": "11.1.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, - "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "locate-path": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" } }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "enhanced-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", + "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "tapable": "1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.6", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" } }, "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "lcid": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "mem": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz" - } - }, - "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" - } - }, - "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "normalize-package-data": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "path-type": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz" - } - }, - "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "read-pkg": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz" - } - }, - "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", - "dev": true, - "requires": { - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" + "ansi-regex": "3.0.0" } }, - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" + "has-flag": "3.0.0" } }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", + "dev": true + }, "which-module": { - "version": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "which-module": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" } }, "yargs-parser": { - "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz" + "camelcase": "4.1.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz", + "integrity": "sha512-I6Mmy/QjWU/kXwCSFGaiOoL5YEQIVmbb0o45xMoCyQAg/mClqZVTcsX327sPfekDyJWpCxb+04whNyLOIxpJdQ==", + "dev": true, + "requires": { + "loud-rejection": "1.6.0", + "memory-fs": "0.4.1", + "mime": "2.3.1", + "path-is-absolute": "1.0.1", + "range-parser": "1.2.0", + "url-join": "4.0.0", + "webpack-log": "1.2.0" + }, + "dependencies": { + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "dev": true + } + } + }, + "webpack-hot-client": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-hot-client/-/webpack-hot-client-3.0.0.tgz", + "integrity": "sha512-6k91015hZ4Okkz8u6OzRgJygEL+3J3ay6HVZhWBF3tT2P0rZJ0mgca39dotJxngggUm3S8707c0vrcynn1IzEQ==", + "dev": true, + "requires": { + "json-stringify-safe": "5.0.1", + "loglevelnext": "1.0.5", + "strip-ansi": "4.0.0", + "uuid": "3.2.1", + "webpack-log": "1.2.0", + "ws": "4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "log-symbols": "2.2.0", + "loglevelnext": "1.0.5", + "uuid": "3.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "webpack-serve": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/webpack-serve/-/webpack-serve-1.0.2.tgz", + "integrity": "sha512-rEymS6lQ+FKv1WWlgxU9ZUMTvNUA6xXSeWEs//CsJjwQ3VnO4NQvZJKn/C72FjdLOJhwlrCKoOJsiml4Jrf/tA==", + "dev": true, + "requires": { + "@shellscape/koa-static": "4.0.5", + "@webpack-contrib/config-loader": "1.1.3", + "chalk": "2.4.1", + "clipboardy": "1.2.3", + "cosmiconfig": "5.0.5", + "debug": "3.1.0", + "find-up": "2.1.0", + "get-port": "3.2.0", + "import-local": "1.0.0", + "killable": "1.0.0", + "koa": "2.5.1", + "koa-webpack": "4.0.0", + "lodash": "4.17.10", + "loud-rejection": "1.6.0", + "meow": "5.0.0", + "nanobus": "4.3.3", + "opn": "5.3.0", + "resolve": "1.7.1", + "time-fix-plugin": "2.0.3", + "update-notifier": "2.5.0", + "url-join": "3.0.0", + "v8-compile-cache": "2.0.0", + "webpack-hot-client": "3.0.0", + "webpack-log": "1.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "map-obj": "2.0.0", + "quick-lru": "1.1.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "4.2.0", + "decamelize-keys": "1.1.0", + "loud-rejection": "1.6.0", + "minimist-options": "3.0.2", + "normalize-package-data": "2.4.0", + "read-pkg-up": "3.0.0", + "redent": "2.0.0", + "trim-newlines": "2.0.0", + "yargs-parser": "10.0.0" + } + }, + "opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.2" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "3.2.0", + "strip-indent": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "url-join": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-3.0.0.tgz", + "integrity": "sha1-JugROs4ZXqMND8OBhuRUAPnOpnI=", + "dev": true + }, + "yargs-parser": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.0.0.tgz", + "integrity": "sha512-+DHejWujTVYeMHLff8U96rLc4uE4Emncoftvn5AjhB1Jw1pWxLzgBUT/WYbPrHmy6YPEBTZQx5myHhVcuuu64g==", + "dev": true, + "requires": { + "camelcase": "4.1.0" } } } }, "webpack-sources": { - "version": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", "dev": true, "requires": { - "source-list-map": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "source-list-map": "2.0.0", + "source-map": "0.6.1" }, "dependencies": { "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, - "webpack-stream": { - "version": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-4.0.0.tgz", - "integrity": "sha1-82c92QfW2bHqe/UfzR24W1/Z4PI=", + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "lodash.clone": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "lodash.some": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "memory-fs": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "webpack": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz" + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "2.1.1" + } + }, + "widest-line": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "dev": true, + "requires": { + "string-width": "2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { - "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "clone": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "clone-buffer": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "cloneable-readable": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz" + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } }, - "websocket-driver": { - "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", - "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, - "requires": { - "http-parser-js": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", - "websocket-extensions": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz" - } - }, - "websocket-extensions": { - "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", - "dev": true - }, - "when": { - "version": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true - }, - "which": { - "version": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", - "dev": true, - "requires": { - "isexe": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - } - }, - "which-module": { - "version": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "window-size": { - "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "wrap-ansi": { - "version": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - } - }, - "wrap-promise": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wrap-promise/-/wrap-promise-1.0.1.tgz", - "integrity": "sha1-sBn0I2zL8ftWCSG0tIcLe9ovUlU=", - "dev": true, - "requires": { - "es6-promise": "2.3.0" - } - }, "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "xregexp": { - "version": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.0.tgz", - "integrity": "sha1-FNhGHgvdOCJL/uUDmgiY/EL80zY=", + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "ws": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", "dev": true }, "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, "y18n": { - "version": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { - "version": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", "dev": true, "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "cliui": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "decamelize": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "get-caller-file": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "os-locale": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "read-pkg-up": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "require-directory": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "require-main-filename": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "which-module": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "y18n": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "yargs-parser": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz" + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" }, "dependencies": { "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true } } }, "yargs-parser": { - "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", "dev": true, "requires": { - "camelcase": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + "camelcase": "3.0.0" }, "dependencies": { "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true } } }, - "zero-fill": { - "version": "https://registry.npmjs.org/zero-fill/-/zero-fill-2.2.3.tgz", - "integrity": "sha1-o97wa6XjmuZEhQu0yirUEStIVek=", - "dev": true + "zone.js": { + "version": "0.8.19", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.19.tgz", + "integrity": "sha512-l9rofaOs6a4y1W8zt4pDmnCUCnYG377dG+5SZlXNWrTWYUuXFqcJZiOarhYiRVR0NI9sH/8ooPJiz4uprB/Mkg==" } } } diff --git a/package.json b/package.json index 9564813729..80ba39f831 100644 --- a/package.json +++ b/package.json @@ -1,56 +1,82 @@ { - "name": "bitwarden", - "version": "1.27.0", - "env": "Production", + "name": "bitwarden-web", + "version": "2.0.0", + "scripts": { + "sub:init": "git submodule update --init --recursive", + "sub:update": "git submodule update --remote", + "sub:pull": "git submodule foreach git pull", + "postinstall": "npm run sub:init", + "build": "webpack --config webpack.config.js", + "build:watch": "webpack-serve --config webpack.config.js", + "build:prod": "cross-env NODE_ENV=production webpack --config webpack.config.js", + "build:prod:watch": "cross-env NODE_ENV=production webpack-serve --config webpack.config.js", + "build:selfhost": "cross-env SELF_HOST=true webpack-serve --config webpack.config.js", + "build:selfhost:watch": "cross-env SELF_HOST=true webpack-serve --config webpack.config.js", + "build:selfhost:prod": "cross-env SELF_HOST=true NODE_ENV=production webpack --config webpack.config.js", + "build:selfhost:prod:watch": "cross-env SELF_HOST=true NODE_ENV=production webpack-serve --config webpack.config.js", + "dist": "npm run build:prod && gulp dist", + "lint": "tslint src/**/*.ts || true", + "lint:fix": "tslint src/**/*.ts --fix" + }, "devDependencies": { - "connect": "3.6.5", - "lodash": "4.17.4", - "gulp": "3.9.1", - "gulp-concat": "2.6.1", - "gulp-cssmin": "0.2.0", - "gulp-less": "3.3.2", - "gulp-rename": "1.2.2", - "gulp-uglify": "3.0.0", - "gulp-gh-pages": "git+https://github.com/tekd/gulp-gh-pages.git#update-dependency", - "gulp-preprocess": "2.0.0", - "gulp-ng-annotate": "2.0.0", - "gulp-ng-config": "1.5.0", - "gulp-connect": "5.0.0", - "gulp-json-editor": "2.2.2", - "jshint": "2.9.5", - "gulp-jshint": "2.0.4", - "rimraf": "2.6.2", - "run-sequence": "2.2.0", - "merge-stream": "1.0.1", - "jquery": "3.2.1", - "font-awesome": "4.7.0", - "bootstrap": "3.3.7", - "angular": "1.6.7", - "angular-resource": "1.6.7", - "angular-sanitize": "1.6.7", - "angular-ui-bootstrap": "2.5.6", - "angular-ui-router": "0.4.2", - "angular-jwt": "0.1.9", - "angular-cookies": "1.6.7", - "admin-lte": "2.3.11", - "angular-toastr": "2.1.1", - "angular-bootstrap-show-errors": "2.3.0", - "angular-messages": "1.6.7", - "ngstorage": "0.3.11", - "papaparse": "4.3.6", - "clipboard": "1.7.1", - "ngclipboard": "1.1.2", - "angulartics": "1.5.0", - "angulartics-google-analytics": "0.4.0", - "node-forge": "0.7.1", - "webpack-stream": "4.0.0", - "angular-stripe": "5.0.0", - "angular-credit-cards": "3.1.6", - "browserify": "14.5.0", - "vinyl-source-stream": "1.1.0", - "gulp-derequire": "2.1.0", - "exposify": "0.5.0", + "@angular/compiler-cli": "5.2.0", + "@ngtools/webpack": "1.10.2", + "@types/jquery": "^3.3.2", + "@types/lunr": "2.1.5", + "@types/node": "8.0.19", + "@types/node-forge": "0.6.10", + "@types/papaparse": "4.1.33", + "@types/webcrypto": "^0.0.28", + "angular2-template-loader": "^0.6.2", + "clean-webpack-plugin": "^0.1.19", + "copy-webpack-plugin": "^4.5.1", + "cross-env": "^5.1.4", + "css-loader": "^0.28.11", + "extract-text-webpack-plugin": "next", + "file-loader": "^1.1.11", + "html-loader": "^0.5.5", + "html-webpack-plugin": "^3.2.0", + "node-sass": "^4.7.2", + "sass-loader": "^7.0.2", + "style-loader": "^0.21.0", + "ts-loader": "^4.3.1", + "tslint": "^5.10.0", + "tslint-loader": "^3.6.0", + "typescript": "^2.7.2", + "webpack": "^4.10.2", + "webpack-cli": "^3.0.2", + "webpack-serve": "^1.0.2" + }, + "dependencies": { + "@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", + "angular2-toaster": "4.0.2", + "angulartics2": "5.0.1", + "bootstrap": "4.1.1", + "core-js": "2.4.1", "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", - "angular-promise-polyfill": "0.0.4" + "font-awesome": "4.7.0", + "jquery": "3.3.1", + "lunr": "2.1.6", + "mousetrap": "1.6.1", + "ngx-infinite-scroll": "0.8.4", + "node-forge": "0.7.1", + "papaparse": "4.3.5", + "popper.js": "1.14.3", + "rxjs": "5.5.6", + "sweetalert": "2.1.0", + "tldjs": "2.0.0", + "web-animations-js": "2.3.1", + "webcrypto-shim": "0.1.4", + "whatwg-fetch": "^2.0.4", + "zone.js": "0.8.19" } } diff --git a/settings.Preview.json b/settings.Preview.json deleted file mode 100644 index aaf40b8a4e..0000000000 --- a/settings.Preview.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "appSettings": { - "apiUri": "/api", - "identityUri": "/identity", - "iconsUri": "https://icons.bitwarden.com", - "stripeKey": "pk_test_KPoCfZXu7mznb9uSCPZ2JpTD", - "braintreeKey": "sandbox_r72q8jq6_9pnxkwm75f87sdc2" - } -} diff --git a/settings.Production.json b/settings.Production.json deleted file mode 100644 index e1b4909f58..0000000000 --- a/settings.Production.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "appSettings": { - "apiUri": "/api", - "identityUri": "/identity", - "iconsUri": "https://icons.bitwarden.com", - "stripeKey": "pk_live_bpN0P37nMxrMQkcaHXtAybJk", - "braintreeKey": "production_qfbsv8kc_njj2zjtyngtjmbjd" - } -} diff --git a/settings.json b/settings.json deleted file mode 100644 index 9029e0ca74..0000000000 --- a/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "appSettings": { - "apiUri": "http://localhost:4000", - "identityUri": "http://localhost:33656", - "iconsUri": "https://icons.bitwarden.com", - "stripeKey": "pk_test_KPoCfZXu7mznb9uSCPZ2JpTD", - "braintreeKey": "sandbox_r72q8jq6_9pnxkwm75f87sdc2" - } -} diff --git a/src/app/accounts/accountsLoginController.js b/src/app/accounts/accountsLoginController.js deleted file mode 100644 index 94a86362f7..0000000000 --- a/src/app/accounts/accountsLoginController.js +++ /dev/null @@ -1,279 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService, - $state, constants, $analytics, $uibModal, $timeout, $window, $filter, toastr) { - $scope.state = $state; - $scope.twoFactorProviderConstants = constants.twoFactorProvider; - $scope.rememberTwoFactor = { checked: false }; - var stopU2fCheck = true; - - $scope.returnState = $state.params.returnState; - $scope.stateEmail = $state.params.email; - if (!$scope.returnState && $state.params.org) { - $scope.returnState = { - name: 'backend.user.settingsCreateOrg', - params: { plan: $state.params.org } - }; - } - else if (!$scope.returnState && $state.params.premium) { - $scope.returnState = { - name: 'backend.user.settingsPremium' - }; - } - - if ($state.current.name.indexOf('twoFactor') > -1 && (!$scope.twoFactorProviders || !$scope.twoFactorProviders.length)) { - $state.go('frontend.login.info', { returnState: $scope.returnState }); - } - - var rememberedEmail = $cookies.get(constants.rememberedEmailCookieName); - if (rememberedEmail || $scope.stateEmail) { - $scope.model = { - email: $scope.stateEmail || rememberedEmail, - rememberEmail: rememberedEmail !== null - }; - - $timeout(function () { - $("#masterPassword").focus(); - }); - } - else { - $timeout(function () { - $("#email").focus(); - }); - } - - var _email, - _masterPassword; - - $scope.twoFactorProviders = null; - $scope.twoFactorProvider = null; - - $scope.login = function (model) { - $scope.loginPromise = authService.logIn(model.email, model.masterPassword).then(function (twoFactorProviders) { - if (model.rememberEmail) { - var cookieExpiration = new Date(); - cookieExpiration.setFullYear(cookieExpiration.getFullYear() + 10); - - $cookies.put( - constants.rememberedEmailCookieName, - model.email, - { expires: cookieExpiration }); - } - else { - $cookies.remove(constants.rememberedEmailCookieName); - } - - if (twoFactorProviders && Object.keys(twoFactorProviders).length > 0) { - _email = model.email; - _masterPassword = model.masterPassword; - - $scope.twoFactorProviders = cleanProviders(twoFactorProviders); - $scope.twoFactorProvider = getDefaultProvider($scope.twoFactorProviders); - - $analytics.eventTrack('Logged In To Two-step'); - $state.go('frontend.login.twoFactor', { returnState: $scope.returnState }).then(function () { - $timeout(function () { - $("#code").focus(); - init(); - }); - }); - } - else { - $analytics.eventTrack('Logged In'); - loggedInGo(); - } - - model.masterPassword = ''; - }); - }; - - function getDefaultProvider(twoFactorProviders) { - var keys = Object.keys(twoFactorProviders); - var providerType = null; - var providerPriority = -1; - for (var i = 0; i < keys.length; i++) { - var provider = $filter('filter')(constants.twoFactorProviderInfo, { type: keys[i], active: true }); - if (provider.length && provider[0].priority > providerPriority) { - if (provider[0].type === constants.twoFactorProvider.u2f && !u2f.isSupported) { - continue; - } - - providerType = provider[0].type; - providerPriority = provider[0].priority; - } - } - - if (providerType === null) { - return null; - } - - return parseInt(providerType); - } - - function cleanProviders(twoFactorProviders) { - if (canUseSecurityKey()) { - return twoFactorProviders; - } - - var keys = Object.keys(twoFactorProviders); - for (var i = 0; i < keys.length; i++) { - var provider = $filter('filter')(constants.twoFactorProviderInfo, { - type: keys[i], - active: true, - requiresUsb: false - }); - if (!provider.length) { - delete twoFactorProviders[keys[i]]; - } - } - - return twoFactorProviders; - } - - // ref: https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser - function canUseSecurityKey() { - var mobile = false; - (function (a) { - if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) { - mobile = true; - } - })(navigator.userAgent || navigator.vendor || window.opera); - - return !mobile && !navigator.userAgent.match(/iPad/i); - } - - $scope.twoFactor = function (token) { - if ($scope.twoFactorProvider === constants.twoFactorProvider.email || - $scope.twoFactorProvider === constants.twoFactorProvider.authenticator) { - token = token.replace(' ', ''); - } - - $scope.twoFactorPromise = authService.logIn(_email, _masterPassword, token, $scope.twoFactorProvider, - $scope.rememberTwoFactor.checked || false); - - $scope.twoFactorPromise.then(function () { - $analytics.eventTrack('Logged In From Two-step'); - loggedInGo(); - }, function () { - if ($scope.twoFactorProvider === constants.twoFactorProvider.u2f) { - init(); - } - }); - }; - - $scope.anotherMethod = function () { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/accounts/views/accountsTwoFactorMethods.html', - controller: 'accountsTwoFactorMethodsController', - resolve: { - providers: function () { return $scope.twoFactorProviders; } - } - }); - - modal.result.then(function (provider) { - $scope.twoFactorProvider = provider; - $timeout(function () { - $("#code").focus(); - init(); - }); - }); - }; - - $scope.sendEmail = function (doToast) { - if ($scope.twoFactorProvider !== constants.twoFactorProvider.email) { - return; - } - - return cryptoService.makeKeyAndHash(_email, _masterPassword).then(function (result) { - return apiService.twoFactor.sendEmailLogin({ - email: _email, - masterPasswordHash: result.hash - }).$promise; - }).then(function () { - if (doToast) { - toastr.success('Verification email sent to ' + $scope.twoFactorEmail + '.'); - } - }, function () { - toastr.error('Could not send verification email.'); - }); - }; - - $scope.$on('$destroy', function () { - stopU2fCheck = true; - }); - - function loggedInGo() { - if ($scope.returnState) { - $state.go($scope.returnState.name, $scope.returnState.params); - } - else { - $state.go('backend.user.vault'); - } - } - - function init() { - stopU2fCheck = true; - var params; - if ($scope.twoFactorProvider === constants.twoFactorProvider.duo || - $scope.twoFactorProvider === constants.twoFactorProvider.organizationDuo) { - params = $scope.twoFactorProviders[$scope.twoFactorProvider]; - - $window.Duo.init({ - host: params.Host, - sig_request: params.Signature, - submit_callback: function (theForm) { - var response = $(theForm).find('input[name="sig_response"]').val(); - $scope.twoFactor(response); - } - }); - } - else if ($scope.twoFactorProvider === constants.twoFactorProvider.u2f) { - stopU2fCheck = false; - params = $scope.twoFactorProviders[constants.twoFactorProvider.u2f]; - var challenges = JSON.parse(params.Challenges); - - initU2f(challenges); - } - else if ($scope.twoFactorProvider === constants.twoFactorProvider.email) { - params = $scope.twoFactorProviders[constants.twoFactorProvider.email]; - $scope.twoFactorEmail = params.Email; - if (Object.keys($scope.twoFactorProviders).length > 1) { - $scope.sendEmail(false); - } - } - } - - function initU2f(challenges) { - if (stopU2fCheck) { - return; - } - - if (challenges.length < 1 || $scope.twoFactorProvider !== constants.twoFactorProvider.u2f) { - return; - } - - console.log('listening for u2f key...'); - - $window.u2f.sign(challenges[0].appId, challenges[0].challenge, [{ - version: challenges[0].version, - keyHandle: challenges[0].keyHandle - }], function (data) { - if ($scope.twoFactorProvider !== constants.twoFactorProvider.u2f) { - return; - } - - if (data.errorCode) { - console.log(data.errorCode); - - $timeout(function () { - initU2f(challenges); - }, data.errorCode === 5 ? 0 : 1000); - - return; - } - $scope.twoFactor(JSON.stringify(data)); - }, 10); - } - }); diff --git a/src/app/accounts/accountsLogoutController.js b/src/app/accounts/accountsLogoutController.js deleted file mode 100644 index 418e968921..0000000000 --- a/src/app/accounts/accountsLogoutController.js +++ /dev/null @@ -1,8 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsLogoutController', function ($scope, authService, $state, $analytics) { - authService.logOut(); - $analytics.eventTrack('Logged Out'); - $state.go('frontend.login.info'); - }); diff --git a/src/app/accounts/accountsModule.js b/src/app/accounts/accountsModule.js deleted file mode 100644 index dfa7f48bce..0000000000 --- a/src/app/accounts/accountsModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.accounts', ['ui.bootstrap', 'ngCookies']); diff --git a/src/app/accounts/accountsOrganizationAcceptController.js b/src/app/accounts/accountsOrganizationAcceptController.js deleted file mode 100644 index 8ff0164ed8..0000000000 --- a/src/app/accounts/accountsOrganizationAcceptController.js +++ /dev/null @@ -1,45 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsOrganizationAcceptController', function ($scope, $state, apiService, authService, toastr, $analytics) { - $scope.state = { - name: $state.current.name, - params: $state.params - }; - - if (!$state.params.organizationId || !$state.params.organizationUserId || !$state.params.token || - !$state.params.email || !$state.params.organizationName) { - $state.go('frontend.login.info').then(function () { - toastr.error('Invalid parameters.'); - }); - return; - } - - $scope.$on('$viewContentLoaded', function () { - if (authService.isAuthenticated()) { - $scope.accepting = true; - apiService.organizationUsers.accept( - { - orgId: $state.params.organizationId, - id: $state.params.organizationUserId - }, - { - token: $state.params.token - }, function () { - $analytics.eventTrack('Accepted Invitation'); - $state.go('backend.user.vault', null, { location: 'replace' }).then(function () { - toastr.success('You can access this organization once an administrator confirms your membership.' + - ' We\'ll send an email when that happens.', 'Invite Accepted', { timeOut: 10000 }); - }); - }, function () { - $analytics.eventTrack('Failed To Accept Invitation'); - $state.go('backend.user.vault', null, { location: 'replace' }).then(function () { - toastr.error('Unable to accept invitation.', 'Error'); - }); - }); - } - else { - $scope.loading = false; - } - }); - }); diff --git a/src/app/accounts/accountsPasswordHintController.js b/src/app/accounts/accountsPasswordHintController.js deleted file mode 100644 index b26a243607..0000000000 --- a/src/app/accounts/accountsPasswordHintController.js +++ /dev/null @@ -1,13 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsPasswordHintController', function ($scope, $rootScope, apiService, $analytics) { - $scope.success = false; - - $scope.submit = function (model) { - $scope.submitPromise = apiService.accounts.postPasswordHint({ email: model.email }, function () { - $analytics.eventTrack('Requested Password Hint'); - $scope.success = true; - }).$promise; - }; - }); diff --git a/src/app/accounts/accountsRecoverController.js b/src/app/accounts/accountsRecoverController.js deleted file mode 100644 index d5db279e20..0000000000 --- a/src/app/accounts/accountsRecoverController.js +++ /dev/null @@ -1,21 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsRecoverController', function ($scope, apiService, cryptoService, $analytics) { - $scope.success = false; - - $scope.submit = function (model) { - var email = model.email.toLowerCase(); - - $scope.submitPromise = cryptoService.makeKeyAndHash(model.email, model.masterPassword).then(function (result) { - return apiService.twoFactor.recover({ - email: email, - masterPasswordHash: result.hash, - recoveryCode: model.code.replace(/\s/g, '').toLowerCase() - }).$promise; - }).then(function () { - $analytics.eventTrack('Recovered 2FA'); - $scope.success = true; - }); - }; - }); diff --git a/src/app/accounts/accountsRecoverDeleteController.js b/src/app/accounts/accountsRecoverDeleteController.js deleted file mode 100644 index a6cc7bb546..0000000000 --- a/src/app/accounts/accountsRecoverDeleteController.js +++ /dev/null @@ -1,13 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsRecoverDeleteController', function ($scope, $rootScope, apiService, $analytics) { - $scope.success = false; - - $scope.submit = function (model) { - $scope.submitPromise = apiService.accounts.postDeleteRecover({ email: model.email }, function () { - $analytics.eventTrack('Started Delete Recovery'); - $scope.success = true; - }).$promise; - }; - }); diff --git a/src/app/accounts/accountsRegisterController.js b/src/app/accounts/accountsRegisterController.js deleted file mode 100644 index ebe9197b95..0000000000 --- a/src/app/accounts/accountsRegisterController.js +++ /dev/null @@ -1,101 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsRegisterController', function ($scope, $location, apiService, cryptoService, validationService, - $analytics, $state, $timeout) { - var params = $location.search(); - var stateParams = $state.params; - $scope.createOrg = stateParams.org; - - if (!stateParams.returnState && stateParams.org) { - $scope.returnState = { - name: 'backend.user.settingsCreateOrg', - params: { plan: $state.params.org } - }; - } - else if (!stateParams.returnState && stateParams.premium) { - $scope.returnState = { - name: 'backend.user.settingsPremium', - params: { plan: $state.params.org } - }; - } - else { - $scope.returnState = stateParams.returnState; - } - - $scope.success = false; - $scope.model = { - email: params.email ? params.email : stateParams.email - }; - $scope.readOnlyEmail = stateParams.email !== null; - - var registerOrgUserId = null; - var registerToken = null; - if(stateParams.returnState && stateParams.returnState.params && - stateParams.returnState.name === 'frontend.organizationAccept') { - registerOrgUserId = stateParams.returnState.params.organizationUserId || null; - registerToken = stateParams.returnState.params.token || null; - } - - $timeout(function () { - if ($scope.model.email) { - $("#name").focus(); - } - else { - $("#email").focus(); - } - }); - - $scope.registerPromise = null; - $scope.register = function (form) { - var error = false; - - if ($scope.model.masterPassword.length < 8) { - validationService.addError(form, 'MasterPassword', 'Master password must be at least 8 characters long.', true); - error = true; - } - if ($scope.model.masterPassword !== $scope.model.confirmMasterPassword) { - validationService.addError(form, 'ConfirmMasterPassword', 'Master password confirmation does not match.', true); - error = true; - } - - if (error) { - return; - } - - var email = $scope.model.email.toLowerCase(); - var makeResult, encKey; - - $scope.registerPromise = cryptoService.makeKeyAndHash(email, $scope.model.masterPassword).then(function (result) { - makeResult = result; - encKey = cryptoService.makeEncKey(result.key); - return cryptoService.makeKeyPair(encKey.encKey); - }).then(function (result) { - var request = { - name: $scope.model.name, - email: email, - masterPasswordHash: makeResult.hash, - masterPasswordHint: $scope.model.masterPasswordHint, - key: encKey.encKeyEnc, - keys: { - publicKey: result.publicKey, - encryptedPrivateKey: result.privateKeyEnc - }, - token: registerToken, - organizationUserId: registerOrgUserId - }; - - return apiService.accounts.register(request).$promise; - }, function (errors) { - validationService.addError(form, null, 'Problem generating keys.', true); - return false; - }).then(function (result) { - if (result === false) { - return; - } - - $scope.success = true; - $analytics.eventTrack('Registered'); - }); - }; - }); diff --git a/src/app/accounts/accountsTwoFactorMethodsController.js b/src/app/accounts/accountsTwoFactorMethodsController.js deleted file mode 100644 index 15c179102f..0000000000 --- a/src/app/accounts/accountsTwoFactorMethodsController.js +++ /dev/null @@ -1,43 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsTwoFactorMethodsController', function ($scope, $uibModalInstance, $analytics, providers, constants) { - $analytics.eventTrack('accountsTwoFactorMethodsController', { category: 'Modal' }); - - $scope.providers = []; - - if (providers.hasOwnProperty(constants.twoFactorProvider.organizationDuo)) { - add(constants.twoFactorProvider.organizationDuo); - } - if (providers.hasOwnProperty(constants.twoFactorProvider.authenticator)) { - add(constants.twoFactorProvider.authenticator); - } - if (providers.hasOwnProperty(constants.twoFactorProvider.yubikey)) { - add(constants.twoFactorProvider.yubikey); - } - if (providers.hasOwnProperty(constants.twoFactorProvider.email)) { - add(constants.twoFactorProvider.email); - } - if (providers.hasOwnProperty(constants.twoFactorProvider.duo)) { - add(constants.twoFactorProvider.duo); - } - if (providers.hasOwnProperty(constants.twoFactorProvider.u2f) && u2f.isSupported) { - add(constants.twoFactorProvider.u2f); - } - - $scope.choose = function (provider) { - $uibModalInstance.close(provider.type); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - - function add(type) { - for (var i = 0; i < constants.twoFactorProviderInfo.length; i++) { - if (constants.twoFactorProviderInfo[i].type === type) { - $scope.providers.push(constants.twoFactorProviderInfo[i]); - } - } - } - }); diff --git a/src/app/accounts/accountsVerifyEmailController.js b/src/app/accounts/accountsVerifyEmailController.js deleted file mode 100644 index 8abcd3660a..0000000000 --- a/src/app/accounts/accountsVerifyEmailController.js +++ /dev/null @@ -1,28 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsVerifyEmailController', function ($scope, $state, apiService, toastr, $analytics) { - if (!$state.params.userId || !$state.params.token) { - $state.go('frontend.login.info').then(function () { - toastr.error('Invalid parameters.'); - }); - return; - } - - $scope.$on('$viewContentLoaded', function () { - apiService.accounts.verifyEmailToken({}, - { - token: $state.params.token, - userId: $state.params.userId - }, function () { - $analytics.eventTrack('Verified Email'); - $state.go('frontend.login.info', null, { location: 'replace' }).then(function () { - toastr.success('Your email has been verified. Thank you.', 'Success'); - }); - }, function () { - $state.go('frontend.login.info', null, { location: 'replace' }).then(function () { - toastr.error('Unable to verify email.', 'Error'); - }); - }); - }); - }); diff --git a/src/app/accounts/accountsVerifyRecoverDeleteController.js b/src/app/accounts/accountsVerifyRecoverDeleteController.js deleted file mode 100644 index e5a056e73e..0000000000 --- a/src/app/accounts/accountsVerifyRecoverDeleteController.js +++ /dev/null @@ -1,36 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsVerifyRecoverDeleteController', function ($scope, $state, apiService, toastr, $analytics) { - if (!$state.params.userId || !$state.params.token || !$state.params.email) { - $state.go('frontend.login.info').then(function () { - toastr.error('Invalid parameters.'); - }); - return; - } - - $scope.email = $state.params.email; - - $scope.delete = function () { - if (!confirm('Are you sure you want to delete this account? This cannot be undone.')) { - return; - } - - $scope.deleting = true; - apiService.accounts.postDeleteRecoverToken({}, - { - token: $state.params.token, - userId: $state.params.userId - }, function () { - $analytics.eventTrack('Recovered Delete'); - $state.go('frontend.login.info', null, { location: 'replace' }).then(function () { - toastr.success('Your account has been deleted. You can register a new account again if you like.', - 'Success'); - }); - }, function () { - $state.go('frontend.login.info', null, { location: 'replace' }).then(function () { - toastr.error('Unable to delete account.', 'Error'); - }); - }); - }; - }); diff --git a/src/app/accounts/hint.component.html b/src/app/accounts/hint.component.html new file mode 100644 index 0000000000..b56867f95d --- /dev/null +++ b/src/app/accounts/hint.component.html @@ -0,0 +1,26 @@ +
+
+
+

{{'passwordHint' | i18n}}

+
+
+
+ + + {{'enterEmailToGetHint' | i18n}} +
+
+
+ + + {{'cancel' | i18n}} + +
+
+
+
+
+
diff --git a/src/app/accounts/hint.component.ts b/src/app/accounts/hint.component.ts new file mode 100644 index 0000000000..bb84ff02f9 --- /dev/null +++ b/src/app/accounts/hint.component.ts @@ -0,0 +1,22 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { HintComponent as BaseHintComponent } from 'jslib/angular/components/hint.component'; + +@Component({ + selector: 'app-hint', + templateUrl: 'hint.component.html', +}) +export class HintComponent extends BaseHintComponent { + constructor(router: Router, analytics: Angulartics2, + toasterService: ToasterService, i18nService: I18nService, + apiService: ApiService) { + super(router, analytics, toasterService, i18nService, apiService); + } +} diff --git a/src/app/accounts/lock.component.html b/src/app/accounts/lock.component.html new file mode 100644 index 0000000000..af465e81ba --- /dev/null +++ b/src/app/accounts/lock.component.html @@ -0,0 +1,34 @@ +
+
+
+

+ +

+

{{'yourVaultIsLocked' | i18n}}

+
+
+
+ +
+ + +
+
+
+
+ + +
+
+
+
+
+
diff --git a/src/app/accounts/lock.component.ts b/src/app/accounts/lock.component.ts new file mode 100644 index 0000000000..70cec1bec6 --- /dev/null +++ b/src/app/accounts/lock.component.ts @@ -0,0 +1,47 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { MessagingService } from 'jslib/abstractions/messaging.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { RouterService } from '../services/router.service'; + +import { LockComponent as BaseLockComponent } from 'jslib/angular/components/lock.component'; + +@Component({ + selector: 'app-lock', + templateUrl: 'lock.component.html', +}) +export class LockComponent extends BaseLockComponent implements OnInit { + constructor(router: Router, analytics: Angulartics2, + toasterService: ToasterService, i18nService: I18nService, + platformUtilsService: PlatformUtilsService, messagingService: MessagingService, + userService: UserService, cryptoService: CryptoService, + private routerService: RouterService) { + super(router, analytics, toasterService, i18nService, platformUtilsService, + messagingService, userService, cryptoService); + } + + async ngOnInit() { + const authed = await this.userService.isAuthenticated(); + if (!authed) { + this.router.navigate(['/']); + } else if (await this.cryptoService.hasKey()) { + this.router.navigate(['vault']); + } + + const previousUrl = this.routerService.getPreviousUrl(); + if (previousUrl !== '/' && previousUrl.indexOf('lock') === -1) { + this.successRoute = previousUrl; + } + } +} diff --git a/src/app/accounts/login.component.html b/src/app/accounts/login.component.html new file mode 100644 index 0000000000..70f222d694 --- /dev/null +++ b/src/app/accounts/login.component.html @@ -0,0 +1,40 @@ +
+
+
+ +

{{'loginOrCreateNewAccount' | i18n}}

+
+
+
+ + +
+
+ +
+ + +
+ + {{'getMasterPasswordHint' | i18n}} + +
+
+
+ + + {{'createAccount' | i18n}} + +
+
+
+
+
+
diff --git a/src/app/accounts/login.component.ts b/src/app/accounts/login.component.ts new file mode 100644 index 0000000000..3904d2bf9c --- /dev/null +++ b/src/app/accounts/login.component.ts @@ -0,0 +1,24 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { AuthService } from 'jslib/abstractions/auth.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; + +import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component'; + +@Component({ + selector: 'app-login', + templateUrl: 'login.component.html', +}) +export class LoginComponent extends BaseLoginComponent { + constructor(authService: AuthService, router: Router, + analytics: Angulartics2, toasterService: ToasterService, + i18nService: I18nService, private syncService: SyncService) { + super(authService, router, analytics, toasterService, i18nService); + this.successRoute = '/vault'; + } +} diff --git a/src/app/accounts/register.component.html b/src/app/accounts/register.component.html new file mode 100644 index 0000000000..fd1e8c3d82 --- /dev/null +++ b/src/app/accounts/register.component.html @@ -0,0 +1,58 @@ +
+
+
+

{{'createAccount' | i18n}}

+
+
+
+ + + {{'emailAddressDesc' | i18n}} +
+
+ + + {{'yourNameDesc' | i18n}} +
+
+ +
+ + +
+ {{'masterPassDesc' | i18n}} +
+
+ +
+ + +
+
+
+ + + {{'masterPassHintDesc' | i18n}} +
+
+
+ + + {{'cancel' | i18n}} + +
+
+
+
+
+
diff --git a/src/app/accounts/register.component.ts b/src/app/accounts/register.component.ts new file mode 100644 index 0000000000..0867b5903c --- /dev/null +++ b/src/app/accounts/register.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { AuthService } from 'jslib/abstractions/auth.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { RegisterComponent as BaseRegisterComponent } from 'jslib/angular/components/register.component'; + +@Component({ + selector: 'app-register', + templateUrl: 'register.component.html', +}) +export class RegisterComponent extends BaseRegisterComponent { + constructor(authService: AuthService, router: Router, + analytics: Angulartics2, toasterService: ToasterService, + i18nService: I18nService, cryptoService: CryptoService, + apiService: ApiService) { + super(authService, router, analytics, toasterService, i18nService, cryptoService, apiService); + } +} diff --git a/src/app/accounts/two-factor-options.component.html b/src/app/accounts/two-factor-options.component.html new file mode 100644 index 0000000000..cfa4c31710 --- /dev/null +++ b/src/app/accounts/two-factor-options.component.html @@ -0,0 +1,26 @@ + diff --git a/src/app/accounts/two-factor-options.component.ts b/src/app/accounts/two-factor-options.component.ts new file mode 100644 index 0000000000..6ab0be4faa --- /dev/null +++ b/src/app/accounts/two-factor-options.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { AuthService } from 'jslib/abstractions/auth.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { + TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent, +} from 'jslib/angular/components/two-factor-options.component'; + +@Component({ + selector: 'app-two-factor-options', + templateUrl: 'two-factor-options.component.html', +}) +export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent { + constructor(authService: AuthService, router: Router, + analytics: Angulartics2, toasterService: ToasterService, + i18nService: I18nService, platformUtilsService: PlatformUtilsService) { + super(authService, router, analytics, toasterService, i18nService, platformUtilsService, window); + } +} diff --git a/src/app/accounts/two-factor.component.html b/src/app/accounts/two-factor.component.html new file mode 100644 index 0000000000..9b5d468472 --- /dev/null +++ b/src/app/accounts/two-factor.component.html @@ -0,0 +1,75 @@ +
+
+
+

{{title}}

+
+
+ +

{{'enterVerificationCodeApp' | i18n}}

+

+ {{'enterVerificationCodeEmail' | i18n : twoFactorEmail}} +

+
+ + + + + {{'sendVerificationCodeEmailAgain' | i18n}} + + +
+
+ +

{{'insertYubiKey' | i18n}}

+ +
+ + +
+
+ +

+ +

+ +

{{'insertU2f' | i18n}}

+ +
+
+ +
+ +
+
+ +
+ + +
+ +

{{'noTwoStepProviders' | i18n}}

+

{{'noTwoStepProviders2' | i18n}}

+
+
+
+ + + {{'cancel' | i18n}} + +
+ +
+
+
+
+
+ + diff --git a/src/app/accounts/two-factor.component.ts b/src/app/accounts/two-factor.component.ts new file mode 100644 index 0000000000..932a9dd775 --- /dev/null +++ b/src/app/accounts/two-factor.component.ts @@ -0,0 +1,59 @@ +import { + Component, + ComponentFactoryResolver, + ViewChild, + ViewContainerRef, +} from '@angular/core'; + +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { TwoFactorOptionsComponent } from './two-factor-options.component'; + +import { ModalComponent } from '../modal.component'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { AuthService } from 'jslib/abstractions/auth.service'; +import { EnvironmentService } from 'jslib/abstractions/environment.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; + +import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib/angular/components/two-factor.component'; + +@Component({ + selector: 'app-two-factor', + templateUrl: 'two-factor.component.html', +}) +export class TwoFactorComponent extends BaseTwoFactorComponent { + @ViewChild('twoFactorOptions', { read: ViewContainerRef }) twoFactorOptionsModal: ViewContainerRef; + + constructor(authService: AuthService, router: Router, + analytics: Angulartics2, toasterService: ToasterService, + i18nService: I18nService, apiService: ApiService, + platformUtilsService: PlatformUtilsService, private syncService: SyncService, + environmentService: EnvironmentService, private componentFactoryResolver: ComponentFactoryResolver) { + super(authService, router, analytics, toasterService, i18nService, apiService, + platformUtilsService, window, environmentService); + } + + anotherMethod() { + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + const modal = this.twoFactorOptionsModal.createComponent(factory).instance; + const childComponent = modal.show(TwoFactorOptionsComponent, + this.twoFactorOptionsModal); + + childComponent.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => { + modal.close(); + this.selectedProviderType = provider; + await this.init(); + }); + childComponent.onRecoverSelected.subscribe(() => { + modal.close(); + }); + } +} diff --git a/src/app/accounts/views/accountsLogin.html b/src/app/accounts/views/accountsLogin.html deleted file mode 100644 index 5775b44a9c..0000000000 --- a/src/app/accounts/views/accountsLogin.html +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/src/app/accounts/views/accountsLoginInfo.html b/src/app/accounts/views/accountsLoginInfo.html deleted file mode 100644 index af9d0ec885..0000000000 --- a/src/app/accounts/views/accountsLoginInfo.html +++ /dev/null @@ -1,49 +0,0 @@ - -
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- - - -
-
- - - -
-
-
-
- -
-
-
- -
-
-
- -
\ No newline at end of file diff --git a/src/app/accounts/views/accountsLoginTwoFactor.html b/src/app/accounts/views/accountsLoginTwoFactor.html deleted file mode 100644 index 744c9ea725..0000000000 --- a/src/app/accounts/views/accountsLoginTwoFactor.html +++ /dev/null @@ -1,168 +0,0 @@ -
- -
- -

- Didn't get the email? - - Send it again - -

-
-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- - - -
-
-
-
- -
-
-
- -
-
-
-
- -
- -
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-

Insert your YubiKey into your computer's USB port, then touch its button.

-

- -

-
- - -
-
-
-
- -
-
-
- -
-
-
-
- -
- -
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- -
-
-
-
- -
-
-
- - Logging in... - -
-
-
-
- -
- -
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-

Insert your Security Key into your computer's USB port. If it has a button, touch it.

-

- -

-
-
-
- -
-
-
- - Logging in... - -
-
-
-
- -
-

- This account has two-step login enabled, however, none of the configured two-step providers are supported by this - web browser. -

- Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported - across web browsers (such as an authenticator app). -
- -
- diff --git a/src/app/accounts/views/accountsOrganizationAccept.html b/src/app/accounts/views/accountsOrganizationAccept.html deleted file mode 100644 index d66e6068ea..0000000000 --- a/src/app/accounts/views/accountsOrganizationAccept.html +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/src/app/accounts/views/accountsPasswordHint.html b/src/app/accounts/views/accountsPasswordHint.html deleted file mode 100644 index 87b9757de7..0000000000 --- a/src/app/accounts/views/accountsPasswordHint.html +++ /dev/null @@ -1,39 +0,0 @@ - diff --git a/src/app/accounts/views/accountsRecover.html b/src/app/accounts/views/accountsRecover.html deleted file mode 100644 index 861a376698..0000000000 --- a/src/app/accounts/views/accountsRecover.html +++ /dev/null @@ -1,56 +0,0 @@ - diff --git a/src/app/accounts/views/accountsRecoverDelete.html b/src/app/accounts/views/accountsRecoverDelete.html deleted file mode 100644 index fb97049c87..0000000000 --- a/src/app/accounts/views/accountsRecoverDelete.html +++ /dev/null @@ -1,39 +0,0 @@ - diff --git a/src/app/accounts/views/accountsRegister.html b/src/app/accounts/views/accountsRegister.html deleted file mode 100644 index 7b3434be32..0000000000 --- a/src/app/accounts/views/accountsRegister.html +++ /dev/null @@ -1,82 +0,0 @@ -
- -
- -
-
-

Account Created!

-

You may now log in to your new account.

-
- Ready to log in? -
-
-
-

Create Organization, Step 1

-

Before creating your organization, you first need to create a free personal account.

-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- - - -

You'll use your email address to log in.

-
-
- - - -

What should we call you?

-
-
- - - -

The master password is the password you use to access your vault.

-
-
- - - -

- It is very important that you do not forget your master password. - There is no way to recover the password in the event that you forget it. -

-
-
- - - -

A master password hint can help you remember your password if you forget it.

-
-
- -
- -
-
-
- By clicking the above "Submit" button, you are agreeing to the - Terms of Service - and the - Privacy Policy. -
-
-
\ No newline at end of file diff --git a/src/app/accounts/views/accountsTwoFactorMethods.html b/src/app/accounts/views/accountsTwoFactorMethods.html deleted file mode 100644 index 7efd3309ac..0000000000 --- a/src/app/accounts/views/accountsTwoFactorMethods.html +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/app/accounts/views/accountsVerifyEmail.html b/src/app/accounts/views/accountsVerifyEmail.html deleted file mode 100644 index 7bd695eacc..0000000000 --- a/src/app/accounts/views/accountsVerifyEmail.html +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/src/app/accounts/views/accountsVerifyRecoverDelete.html b/src/app/accounts/views/accountsVerifyRecoverDelete.html deleted file mode 100644 index 0821995c18..0000000000 --- a/src/app/accounts/views/accountsVerifyRecoverDelete.html +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/src/app/apiInterceptor.js b/src/app/apiInterceptor.js deleted file mode 100644 index 76a79c2255..0000000000 --- a/src/app/apiInterceptor.js +++ /dev/null @@ -1,33 +0,0 @@ -angular - .module('bit') - - .factory('apiInterceptor', function ($injector, $q, toastr, appSettings, utilsService) { - return { - request: function (config) { - if (config.url.indexOf(appSettings.apiUri + '/') === 0) { - config.headers['Device-Type'] = utilsService.getDeviceType(); - } - - return config; - }, - response: function (response) { - if (response.status === 401 || response.status === 403) { - $injector.get('authService').logOut(); - $injector.get('$state').go('frontend.login.info').then(function () { - toastr.warning('Your login session has expired.', 'Logged out'); - }); - } - - return response || $q.when(response); - }, - responseError: function (rejection) { - if (rejection.status === 401 || rejection.status === 403) { - $injector.get('authService').logOut(); - $injector.get('$state').go('frontend.login.info').then(function () { - toastr.warning('Your login session has expired.', 'Logged out'); - }); - } - return $q.reject(rejection); - } - }; - }); \ No newline at end of file diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts new file mode 100644 index 0000000000..da5ee012b0 --- /dev/null +++ b/src/app/app-routing.module.ts @@ -0,0 +1,161 @@ +import { NgModule } from '@angular/core'; +import { + RouterModule, + Routes, +} from '@angular/router'; + +import { FrontendLayoutComponent } from './layouts/frontend-layout.component'; +import { OrganizationLayoutComponent } from './layouts/organization-layout.component'; +import { UserLayoutComponent } from './layouts/user-layout.component'; + +import { HintComponent } from './accounts/hint.component'; +import { LockComponent } from './accounts/lock.component'; +import { LoginComponent } from './accounts/login.component'; +import { RegisterComponent } from './accounts/register.component'; +import { TwoFactorComponent } from './accounts/two-factor.component'; + +import { CollectionsComponent as OrgManageCollectionsComponent } from './organizations/manage/collections.component'; +import { EventsComponent as OrgEventsComponent } from './organizations/manage/events.component'; +import { GroupsComponent as OrgGroupsComponent } from './organizations/manage/groups.component'; +import { ManageComponent as OrgManageComponent } from './organizations/manage/manage.component'; +import { PeopleComponent as OrgPeopleComponent } from './organizations/manage/people.component'; + +import { ExportComponent as OrgExportComponent } from './organizations/tools/export.component'; +import { ImportComponent as OrgImportComponent } from './organizations/tools/import.component'; +import { ToolsComponent as OrgToolsComponent } from './organizations/tools/tools.component'; + +import { VaultComponent as OrgVaultComponent } from './organizations/vault/vault.component'; + +import { AccountComponent } from './settings/account.component'; +import { CreateOrganizationComponent } from './settings/create-organization.component'; +import { DomainRulesComponent } from './settings/domain-rules.component'; +import { OptionsComponent } from './settings/options.component'; +import { OrganizationsComponent } from './settings/organizations.component'; +import { PremiumComponent } from './settings/premium.component'; +import { SettingsComponent } from './settings/settings.component'; +import { TwoFactorSetupComponent } from './settings/two-factor-setup.component'; +import { UserBillingComponent } from './settings/user-billing.component'; + +import { BreachReportComponent } from './tools/breach-report.component'; +import { ExportComponent } from './tools/export.component'; +import { ImportComponent } from './tools/import.component'; +import { PasswordGeneratorComponent } from './tools/password-generator.component'; +import { ToolsComponent } from './tools/tools.component'; + +import { VaultComponent } from './vault/vault.component'; + +import { OrganizationGuardService } from './services/organization-guard.service'; +import { OrganizationTypeGuardService } from './services/organization-type-guard.service'; +import { UnauthGuardService } from './services/unauth-guard.service'; + +import { AuthGuardService } from 'jslib/angular/services/auth-guard.service'; + +import { OrganizationUserType } from 'jslib/enums/organizationUserType'; + +const routes: Routes = [ + { + path: '', + component: FrontendLayoutComponent, + children: [ + { path: '', pathMatch: 'full', component: LoginComponent, canActivate: [UnauthGuardService] }, + { path: '2fa', component: TwoFactorComponent, canActivate: [UnauthGuardService] }, + { + path: 'register', component: RegisterComponent, + canActivate: [UnauthGuardService], + data: { titleId: 'createAccount' }, + }, + { + path: 'hint', component: HintComponent, + canActivate: [UnauthGuardService], + data: { titleId: 'passwordHint' }, + }, + { path: 'lock', component: LockComponent }, + ], + }, + { + path: '', + component: UserLayoutComponent, + canActivate: [AuthGuardService], + children: [ + { path: 'vault', component: VaultComponent, data: { titleId: 'myVault' } }, + { + path: 'settings', + component: SettingsComponent, + children: [ + { path: '', pathMatch: 'full', redirectTo: 'account' }, + { path: 'account', component: AccountComponent, data: { titleId: 'myAccount' } }, + { path: 'options', component: OptionsComponent, data: { titleId: 'options' } }, + { path: 'domain-rules', component: DomainRulesComponent, data: { titleId: 'domainRules' } }, + { path: 'two-factor', component: TwoFactorSetupComponent, data: { titleId: 'twoStepLogin' } }, + { path: 'premium', component: PremiumComponent, data: { titleId: 'goPremium' } }, + { path: 'billing', component: UserBillingComponent, data: { titleId: 'billingAndLicensing' } }, + { path: 'organizations', component: OrganizationsComponent, data: { titleId: 'organizations' } }, + { + path: 'create-organization', + component: CreateOrganizationComponent, + data: { titleId: 'newOrganization' }, + }, + ], + }, + { + path: 'tools', + component: ToolsComponent, + canActivate: [AuthGuardService], + children: [ + { path: '', pathMatch: 'full', redirectTo: 'generator' }, + { path: 'import', component: ImportComponent, data: { titleId: 'importData' } }, + { path: 'export', component: ExportComponent, data: { titleId: 'exportVault' } }, + { + path: 'generator', + component: PasswordGeneratorComponent, + data: { titleId: 'passwordGenerator' }, + }, + { path: 'breach-report', component: BreachReportComponent, data: { titleId: 'dataBreachReport' } }, + ], + }, + ], + }, + { + path: 'organizations/:organizationId', + component: OrganizationLayoutComponent, + canActivate: [AuthGuardService, OrganizationGuardService], + children: [ + { path: '', pathMatch: 'full', redirectTo: 'vault' }, + { path: 'vault', component: OrgVaultComponent, data: { titleId: 'vault' } }, + { + path: 'tools', + component: OrgToolsComponent, + canActivate: [OrganizationTypeGuardService], + data: { allowedTypes: [OrganizationUserType.Owner, OrganizationUserType.Admin] }, + children: [ + { path: '', pathMatch: 'full', redirectTo: 'import' }, + { path: 'import', component: OrgImportComponent, data: { titleId: 'importData' } }, + { path: 'export', component: OrgExportComponent, data: { titleId: 'exportVault' } }, + ], + }, + { + path: 'manage', + component: OrgManageComponent, + canActivate: [OrganizationTypeGuardService], + data: { allowedTypes: [OrganizationUserType.Owner, OrganizationUserType.Admin] }, + children: [ + { path: '', pathMatch: 'full', redirectTo: 'people' }, + { path: 'collections', component: OrgManageCollectionsComponent, data: { titleId: 'collections' } }, + { path: 'events', component: OrgEventsComponent, data: { titleId: 'eventLogs' } }, + { path: 'groups', component: OrgGroupsComponent, data: { titleId: 'groups' } }, + { path: 'people', component: OrgPeopleComponent, data: { titleId: 'people' } }, + ], + }, + ], + }, + { path: '**', redirectTo: '' }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes, { + useHash: true, + /*enableTracing: true,*/ + })], + exports: [RouterModule], +}) +export class AppRoutingModule { } diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000000..307007679b --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,2 @@ + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000000..63f714e89e --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,161 @@ +import * as jq from 'jquery'; +import * as _swal from 'sweetalert'; +import { SweetAlert } from 'sweetalert/typings/core'; + +import { + ToasterConfig, + ToasterContainerComponent, + ToasterService, +} from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { + Component, + NgZone, + OnDestroy, + OnInit, +} from '@angular/core'; +import { + NavigationEnd, + Router, +} from '@angular/router'; + +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + +import { StorageService } from 'jslib/abstractions/storage.service'; + +import { AuthService } from 'jslib/abstractions/auth.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { LockService } from 'jslib/abstractions/lock.service'; +import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SettingsService } from 'jslib/abstractions/settings.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; +import { TokenService } from 'jslib/abstractions/token.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { ConstantsService } from 'jslib/services/constants.service'; + +import { RouterService } from './services/router.service'; + +const BroadcasterSubscriptionId = 'AppComponent'; +// Hack due to Angular 5.2 bug +const swal: SweetAlert = _swal as any; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', +}) +export class AppComponent implements OnDestroy, OnInit { + toasterConfig: ToasterConfig = new ToasterConfig({ + showCloseButton: true, + mouseoverTimerStop: true, + animation: 'flyRight', + limit: 5, + }); + + private lastActivity: number = null; + + constructor(private broadcasterService: BroadcasterService, private userService: UserService, + private tokenService: TokenService, private folderService: FolderService, + private settingsService: SettingsService, private syncService: SyncService, + private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService, + private authService: AuthService, private router: Router, private analytics: Angulartics2, + private toasterService: ToasterService, private i18nService: I18nService, + private platformUtilsService: PlatformUtilsService, private ngZone: NgZone, + private lockService: LockService, private storageService: StorageService, + private cryptoService: CryptoService, private collectionService: CollectionService, + private routerService: RouterService) { } + + ngOnInit() { + this.ngZone.runOutsideAngular(() => { + window.onmousemove = () => this.recordActivity(); + window.onmousedown = () => this.recordActivity(); + window.ontouchstart = () => this.recordActivity(); + window.onclick = () => this.recordActivity(); + window.onscroll = () => this.recordActivity(); + window.onkeypress = () => this.recordActivity(); + }); + + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case 'loggedIn': + case 'unlocked': + case 'loggedOut': + break; + case 'logout': + this.logOut(!!message.expired); + break; + case 'lockVault': + await this.lockService.lock(); + break; + case 'locked': + this.router.navigate(['lock']); + break; + case 'syncStarted': + break; + case 'syncCompleted': + break; + default: + } + }); + }); + + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + const modals = Array.from(document.querySelectorAll('.modal')); + for (const modal of modals) { + (jq(modal) as any).modal('hide'); + } + + if (document.querySelector('.swal-modal') != null) { + swal.close(undefined); + } + } + }); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + private async logOut(expired: boolean) { + const userId = await this.userService.getUserId(); + + await Promise.all([ + this.syncService.setLastSync(new Date(0)), + this.tokenService.clearToken(), + this.cryptoService.clearKeys(), + this.userService.clear(), + this.settingsService.clear(userId), + this.cipherService.clear(userId), + this.folderService.clear(userId), + this.collectionService.clear(userId), + this.passwordGenerationService.clear(), + ]); + + this.authService.logOut(async () => { + this.analytics.eventTrack.next({ action: 'Logged Out' }); + if (expired) { + this.toasterService.popAsync('warning', this.i18nService.t('loggedOut'), + this.i18nService.t('loginExpired')); + } + this.router.navigate(['/']); + }); + } + + private async recordActivity() { + const now = (new Date()).getTime(); + if (this.lastActivity != null && now - this.lastActivity < 250) { + return; + } + + this.lastActivity = now; + this.storageService.save(ConstantsService.lastActiveKey, now); + } +} diff --git a/src/app/app.js b/src/app/app.js deleted file mode 100644 index 496bb2ac18..0000000000 --- a/src/app/app.js +++ /dev/null @@ -1,27 +0,0 @@ -angular - .module('bit', [ - 'ui.router', - 'ngMessages', - 'angular-jwt', - 'ui.bootstrap.showErrors', - 'toastr', - 'angulartics', - // @if !selfHosted - 'angulartics.google.analytics', - 'angular-stripe', - 'credit-cards', - // @endif - 'angular-promise-polyfill', - - 'bit.directives', - 'bit.filters', - 'bit.services', - - 'bit.global', - 'bit.accounts', - 'bit.vault', - 'bit.settings', - 'bit.tools', - 'bit.organization', - 'bit.reports' - ]); diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000000..2c8518040d --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,246 @@ +import 'core-js'; + +import { ToasterModule } from 'angular2-toaster'; +import { Angulartics2Module } from 'angulartics2'; +import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; + +import { AppRoutingModule } from './app-routing.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 { ServicesModule } from './services/services.module'; + +import { AppComponent } from './app.component'; +import { ModalComponent } from './modal.component'; + +import { AvatarComponent } from './components/avatar.component'; +import { CalloutComponent } from './components/callout.component'; + +import { FooterComponent } from './layouts/footer.component'; +import { FrontendLayoutComponent } from './layouts/frontend-layout.component'; +import { NavbarComponent } from './layouts/navbar.component'; +import { OrganizationLayoutComponent } from './layouts/organization-layout.component'; +import { UserLayoutComponent } from './layouts/user-layout.component'; + +import { HintComponent } from './accounts/hint.component'; +import { LockComponent } from './accounts/lock.component'; +import { LoginComponent } from './accounts/login.component'; +import { RegisterComponent } from './accounts/register.component'; +import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component'; +import { TwoFactorComponent } from './accounts/two-factor.component'; + +import { CollectionsComponent as OrgManageCollectionsComponent } from './organizations/manage/collections.component'; +import { EventsComponent as OrgEventsComponent } from './organizations/manage/events.component'; +import { GroupAddEditComponent as OrgGroupAddEditComponent } from './organizations/manage/group-add-edit.component'; +import { GroupsComponent as OrgGroupsComponent } from './organizations/manage/groups.component'; +import { ManageComponent as OrgManageComponent } from './organizations/manage/manage.component'; +import { PeopleComponent as OrgPeopleComponent } from './organizations/manage/people.component'; + +import { ExportComponent as OrgExportComponent } from './organizations/tools/export.component'; +import { ImportComponent as OrgImportComponent } from './organizations/tools/import.component'; +import { ToolsComponent as OrgToolsComponent } from './organizations/tools/tools.component'; + +import { AddEditComponent as OrgAddEditComponent } from './organizations/vault/add-edit.component'; +import { AttachmentsComponent as OrgAttachmentsComponent } from './organizations/vault/attachments.component'; +import { CiphersComponent as OrgCiphersComponent } from './organizations/vault/ciphers.component'; +import { CollectionsComponent as OrgCollectionsComponent } from './organizations/vault/collections.component'; +import { GroupingsComponent as OrgGroupingsComponent } from './organizations/vault/groupings.component'; +import { VaultComponent as OrgVaultComponent } from './organizations/vault/vault.component'; + +import { AccountComponent } from './settings/account.component'; +import { AdjustPaymentComponent } from './settings/adjust-payment.component'; +import { AdjustStorageComponent } from './settings/adjust-storage.component'; +import { ChangeEmailComponent } from './settings/change-email.component'; +import { ChangePasswordComponent } from './settings/change-password.component'; +import { CreateOrganizationComponent } from './settings/create-organization.component'; +import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component'; +import { DeleteAccountComponent } from './settings/delete-account.component'; +import { DomainRulesComponent } from './settings/domain-rules.component'; +import { OptionsComponent } from './settings/options.component'; +import { OrganizationsComponent } from './settings/organizations.component'; +import { PaymentComponent } from './settings/payment.component'; +import { PremiumComponent } from './settings/premium.component'; +import { ProfileComponent } from './settings/profile.component'; +import { PurgeVaultComponent } from './settings/purge-vault.component'; +import { SettingsComponent } from './settings/settings.component'; +import { TwoFactorAuthenticatorComponent } from './settings/two-factor-authenticator.component'; +import { TwoFactorDuoComponent } from './settings/two-factor-duo.component'; +import { TwoFactorEmailComponent } from './settings/two-factor-email.component'; +import { TwoFactorRecoveryComponent } from './settings/two-factor-recovery.component'; +import { TwoFactorSetupComponent } from './settings/two-factor-setup.component'; +import { TwoFactorU2fComponent } from './settings/two-factor-u2f.component'; +import { TwoFactorVerifyComponent } from './settings/two-factor-verify.component'; +import { TwoFactorYubiKeyComponent } from './settings/two-factor-yubikey.component'; +import { UpdateLicenseComponent } from './settings/update-license.component'; +import { UserBillingComponent } from './settings/user-billing.component'; + +import { BreachReportComponent } from './tools/breach-report.component'; +import { ExportComponent } from './tools/export.component'; +import { ImportComponent } from './tools/import.component'; +import { PasswordGeneratorHistoryComponent } from './tools/password-generator-history.component'; +import { PasswordGeneratorComponent } from './tools/password-generator.component'; +import { ToolsComponent } from './tools/tools.component'; + +import { AddEditComponent } from './vault/add-edit.component'; +import { AttachmentsComponent } from './vault/attachments.component'; +import { BulkDeleteComponent } from './vault/bulk-delete.component'; +import { BulkMoveComponent } from './vault/bulk-move.component'; +import { BulkShareComponent } from './vault/bulk-share.component'; +import { CiphersComponent } from './vault/ciphers.component'; +import { CollectionsComponent } from './vault/collections.component'; +import { FolderAddEditComponent } from './vault/folder-add-edit.component'; +import { GroupingsComponent } from './vault/groupings.component'; +import { ShareComponent } from './vault/share.component'; +import { VaultComponent } from './vault/vault.component'; + +import { IconComponent } from 'jslib/angular/components/icon.component'; + +import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive'; +import { AutofocusDirective } from 'jslib/angular/directives/autofocus.directive'; +import { BlurClickDirective } from 'jslib/angular/directives/blur-click.directive'; +import { BoxRowDirective } from 'jslib/angular/directives/box-row.directive'; +import { FallbackSrcDirective } from 'jslib/angular/directives/fallback-src.directive'; +import { InputVerbatimDirective } from 'jslib/angular/directives/input-verbatim.directive'; +import { StopClickDirective } from 'jslib/angular/directives/stop-click.directive'; +import { StopPropDirective } from 'jslib/angular/directives/stop-prop.directive'; +import { TrueFalseValueDirective } from 'jslib/angular/directives/true-false-value.directive'; + +import { I18nPipe } from 'jslib/angular/pipes/i18n.pipe'; +import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe'; +import { SearchPipe } from 'jslib/angular/pipes/search.pipe'; + +@NgModule({ + imports: [ + BrowserModule, + BrowserAnimationsModule, + FormsModule, + AppRoutingModule, + ServicesModule, + Angulartics2Module.forRoot([Angulartics2GoogleAnalytics], { + pageTracking: { + clearQueryParams: true, + }, + }), + ToasterModule, + ], + declarations: [ + AccountComponent, + AddEditComponent, + AdjustPaymentComponent, + AdjustStorageComponent, + ApiActionDirective, + AppComponent, + AttachmentsComponent, + AutofocusDirective, + AvatarComponent, + BlurClickDirective, + BoxRowDirective, + BreachReportComponent, + BulkDeleteComponent, + BulkMoveComponent, + BulkShareComponent, + CalloutComponent, + ChangeEmailComponent, + ChangePasswordComponent, + CiphersComponent, + CollectionsComponent, + CreateOrganizationComponent, + DeauthorizeSessionsComponent, + DeleteAccountComponent, + DomainRulesComponent, + ExportComponent, + FallbackSrcDirective, + FolderAddEditComponent, + FooterComponent, + FrontendLayoutComponent, + GroupingsComponent, + HintComponent, + IconComponent, + I18nPipe, + ImportComponent, + InputVerbatimDirective, + LockComponent, + LoginComponent, + ModalComponent, + NavbarComponent, + OptionsComponent, + OrgAddEditComponent, + OrgAttachmentsComponent, + OrgCiphersComponent, + OrgCollectionsComponent, + OrgEventsComponent, + OrgExportComponent, + OrgImportComponent, + OrgGroupAddEditComponent, + OrgGroupingsComponent, + OrgGroupsComponent, + OrgManageCollectionsComponent, + OrgManageComponent, + OrgPeopleComponent, + OrgToolsComponent, + OrganizationsComponent, + OrganizationLayoutComponent, + OrgVaultComponent, + PasswordGeneratorComponent, + PasswordGeneratorHistoryComponent, + PaymentComponent, + PremiumComponent, + ProfileComponent, + PurgeVaultComponent, + RegisterComponent, + SearchCiphersPipe, + SearchPipe, + SettingsComponent, + ShareComponent, + StopClickDirective, + StopPropDirective, + ToolsComponent, + TrueFalseValueDirective, + TwoFactorAuthenticatorComponent, + TwoFactorComponent, + TwoFactorDuoComponent, + TwoFactorEmailComponent, + TwoFactorOptionsComponent, + TwoFactorRecoveryComponent, + TwoFactorSetupComponent, + TwoFactorU2fComponent, + TwoFactorVerifyComponent, + TwoFactorYubiKeyComponent, + UpdateLicenseComponent, + UserBillingComponent, + UserLayoutComponent, + VaultComponent, + ], + entryComponents: [ + AddEditComponent, + AttachmentsComponent, + BulkDeleteComponent, + BulkMoveComponent, + BulkShareComponent, + CollectionsComponent, + DeauthorizeSessionsComponent, + DeleteAccountComponent, + FolderAddEditComponent, + ModalComponent, + OrgAddEditComponent, + OrgAttachmentsComponent, + OrgCollectionsComponent, + OrgGroupAddEditComponent, + PasswordGeneratorHistoryComponent, + PurgeVaultComponent, + ShareComponent, + TwoFactorAuthenticatorComponent, + TwoFactorDuoComponent, + TwoFactorEmailComponent, + TwoFactorOptionsComponent, + TwoFactorRecoveryComponent, + TwoFactorU2fComponent, + TwoFactorYubiKeyComponent, + ], + providers: [], + bootstrap: [AppComponent], +}) +export class AppModule { } diff --git a/src/app/components/avatar.component.ts b/src/app/components/avatar.component.ts new file mode 100644 index 0000000000..91105b17da --- /dev/null +++ b/src/app/components/avatar.component.ts @@ -0,0 +1,115 @@ +import { + Component, + Input, + OnChanges, + OnInit, +} from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Component({ + selector: 'app-avatar', + template: '', +}) +export class AvatarComponent implements OnChanges, OnInit { + @Input() data: string; + @Input() width = 45; + @Input() height = 45; + @Input() charCount = 2; + @Input() textColor = '#ffffff'; + @Input() fontSize = 20; + @Input() fontWeight = 300; + @Input() dynamic = false; + @Input() circle = false; + + src: string; + + constructor(public sanitizer: DomSanitizer) { } + + ngOnInit() { + if (!this.dynamic) { + this.generate(); + } + } + + ngOnChanges() { + if (this.dynamic) { + this.generate(); + } + } + + private generate() { + let chars: string = null; + const upperData = this.data.toUpperCase(); + + if (this.charCount > 1) { + chars = this.getFirstLetters(upperData, this.charCount); + } + if (chars == null) { + chars = upperData.substr(0, this.charCount); + } + + const charObj = this.getCharText(chars); + const color = this.stringToColor(upperData); + const svg = this.getSvg(this.width, this.height, color); + svg.appendChild(charObj); + const html = window.document.createElement('div').appendChild(svg).outerHTML; + const svgHtml = window.btoa(unescape(encodeURIComponent(html))); + this.src = 'data:image/svg+xml;base64,' + svgHtml; + } + + private stringToColor(str: string): string { + let hash = 0; + for (let i = 0; i < str.length; i++) { + // tslint:disable-next-line + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + let color = '#'; + for (let i = 0; i < 3; i++) { + // tslint:disable-next-line + const value = (hash >> (i * 8)) & 0xFF; + color += ('00' + value.toString(16)).substr(-2); + } + return color; + } + + private getFirstLetters(data: string, count: number): string { + const parts = data.split(' '); + if (parts.length > 1) { + let text = ''; + for (let i = 0; i < count; i++) { + text += parts[i].substr(0, 1); + } + return text; + } + return null; + } + + private getSvg(width: number, height: number, color: string): HTMLElement { + const svgTag = window.document.createElement('svg'); + svgTag.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); + svgTag.setAttribute('pointer-events', 'none'); + svgTag.setAttribute('width', width.toString()); + svgTag.setAttribute('height', height.toString()); + svgTag.style.backgroundColor = color; + svgTag.style.width = width + 'px'; + svgTag.style.height = height + 'px'; + return svgTag; + } + + private getCharText(character: string): HTMLElement { + const textTag = window.document.createElement('text'); + textTag.setAttribute('text-anchor', 'middle'); + textTag.setAttribute('y', '50%'); + textTag.setAttribute('x', '50%'); + textTag.setAttribute('dy', '0.35em'); + textTag.setAttribute('pointer-events', 'auto'); + textTag.setAttribute('fill', this.textColor); + textTag.setAttribute('font-family', '"Open Sans","Helvetica Neue",Helvetica,Arial,' + + 'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"'); + textTag.textContent = character; + textTag.style.fontWeight = this.fontWeight.toString(); + textTag.style.fontSize = this.fontSize + 'px'; + return textTag; + } +} diff --git a/src/app/components/callout.component.html b/src/app/components/callout.component.html new file mode 100644 index 0000000000..0093b78c2d --- /dev/null +++ b/src/app/components/callout.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/components/callout.component.ts b/src/app/components/callout.component.ts new file mode 100644 index 0000000000..34af2873c4 --- /dev/null +++ b/src/app/components/callout.component.ts @@ -0,0 +1,53 @@ +import { + Component, + Input, + OnInit, +} from '@angular/core'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; + +@Component({ + selector: 'app-callout', + templateUrl: 'callout.component.html', +}) +export class CalloutComponent implements OnInit { + @Input() type = 'info'; + @Input() icon: string; + @Input() title: string; + + calloutStyle: string; + + constructor(private i18nService: I18nService) { } + + ngOnInit() { + this.calloutStyle = this.type; + + if (this.type === 'warning' || this.type === 'danger') { + if (this.type === 'danger') { + this.calloutStyle = 'danger'; + } + if (this.title === undefined) { + this.title = this.i18nService.t('warning'); + } + if (this.icon === undefined) { + this.icon = 'fa-warning'; + } + } else if (this.type === 'error') { + this.calloutStyle = 'danger'; + if (this.title === undefined) { + this.title = this.i18nService.t('error'); + } + if (this.icon === undefined) { + this.icon = 'fa-bolt'; + } + } else if (this.type === 'tip') { + this.calloutStyle = 'success'; + if (this.title === undefined) { + this.title = this.i18nService.t('tip'); + } + if (this.icon === undefined) { + this.icon = 'fa-lightbulb-o'; + } + } + } +} diff --git a/src/app/config.js b/src/app/config.js deleted file mode 100644 index 0b665f3fb3..0000000000 --- a/src/app/config.js +++ /dev/null @@ -1,367 +0,0 @@ -angular - .module('bit') - - .config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider, jwtOptionsProvider, - $uibTooltipProvider, toastrConfig, $locationProvider, $qProvider, appSettings - // @if !selfHosted - /* jshint ignore:start */ - , stripeProvider - /* jshint ignore:end */ - // @endif - ) { - angular.extend(appSettings, window.bitwardenAppSettings); - - $qProvider.errorOnUnhandledRejections(false); - $locationProvider.hashPrefix(''); - - jwtOptionsProvider.config({ - whiteListedDomains: ['localhost', 'api.bitwarden.com', 'vault.bitwarden.com', 'haveibeenpwned.com'] - }); - - var refreshPromise; - jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (options, tokenService, authService) { - if (options.url.indexOf(appSettings.apiUri + '/') !== 0) { - return; - } - - if (refreshPromise) { - return refreshPromise; - } - - var token = tokenService.getToken(); - if (!token) { - return; - } - - if (!tokenService.tokenNeedsRefresh(token)) { - return token; - } - - var p = authService.refreshAccessToken(); - if (!p) { - return; - } - - refreshPromise = p.then(function (newToken) { - refreshPromise = null; - return newToken || token; - }); - return refreshPromise; - }; - - // @if !selfHosted - stripeProvider.setPublishableKey(appSettings.stripeKey); - // @endif - - angular.extend(toastrConfig, { - closeButton: true, - progressBar: true, - showMethod: 'slideDown', - target: '.toast-target' - }); - - $uibTooltipProvider.options({ - popupDelay: 600, - appendToBody: true - }); - - // stop IE from caching get requests - if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) { - if (!$httpProvider.defaults.headers.get) { - $httpProvider.defaults.headers.get = {}; - } - $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; - $httpProvider.defaults.headers.get.Pragma = 'no-cache'; - } - - $httpProvider.interceptors.push('apiInterceptor'); - $httpProvider.interceptors.push('jwtInterceptor'); - - $urlRouterProvider.otherwise('/'); - - $stateProvider - // Backend - .state('backend', { - templateUrl: 'app/views/backendLayout.html', - abstract: true, - data: { - authorize: true - } - }) - .state('backend.user', { - templateUrl: 'app/views/userLayout.html', - abstract: true - }) - .state('backend.user.vault', { - url: '^/vault', - templateUrl: 'app/vault/views/vault.html', - controller: 'vaultController', - data: { - pageTitle: 'My Vault', - controlSidebar: true - }, - params: { - refreshFromServer: false - } - }) - .state('backend.user.settings', { - url: '^/settings', - templateUrl: 'app/settings/views/settings.html', - controller: 'settingsController', - data: { pageTitle: 'Settings' } - }) - .state('backend.user.settingsDomains', { - url: '^/settings/domains', - templateUrl: 'app/settings/views/settingsDomains.html', - controller: 'settingsDomainsController', - data: { pageTitle: 'Domain Settings' } - }) - .state('backend.user.settingsTwoStep', { - url: '^/settings/two-step', - templateUrl: 'app/settings/views/settingsTwoStep.html', - controller: 'settingsTwoStepController', - data: { pageTitle: 'Two-step Login' } - }) - .state('backend.user.settingsCreateOrg', { - url: '^/settings/create-organization', - templateUrl: 'app/settings/views/settingsCreateOrganization.html', - controller: 'settingsCreateOrganizationController', - data: { pageTitle: 'Create Organization' } - }) - .state('backend.user.settingsBilling', { - url: '^/settings/billing', - templateUrl: 'app/settings/views/settingsBilling.html', - controller: 'settingsBillingController', - data: { pageTitle: 'Billing' } - }) - .state('backend.user.settingsPremium', { - url: '^/settings/premium', - templateUrl: 'app/settings/views/settingsPremium.html', - controller: 'settingsPremiumController', - data: { pageTitle: 'Go Premium' } - }) - .state('backend.user.tools', { - url: '^/tools', - templateUrl: 'app/tools/views/tools.html', - controller: 'toolsController', - data: { pageTitle: 'Tools' } - }) - .state('backend.user.reportsBreach', { - url: '^/reports/breach', - templateUrl: 'app/reports/views/reportsBreach.html', - controller: 'reportsBreachController', - data: { pageTitle: 'Data Breach Report' } - }) - .state('backend.org', { - templateUrl: 'app/views/organizationLayout.html', - abstract: true - }) - .state('backend.org.dashboard', { - url: '^/organization/:orgId', - templateUrl: 'app/organization/views/organizationDashboard.html', - controller: 'organizationDashboardController', - data: { pageTitle: 'Organization Dashboard' } - }) - .state('backend.org.people', { - url: '/organization/:orgId/people?viewEvents&search', - templateUrl: 'app/organization/views/organizationPeople.html', - controller: 'organizationPeopleController', - data: { pageTitle: 'Organization People' } - }) - .state('backend.org.collections', { - url: '/organization/:orgId/collections?search', - templateUrl: 'app/organization/views/organizationCollections.html', - controller: 'organizationCollectionsController', - data: { pageTitle: 'Organization Collections' } - }) - .state('backend.org.settings', { - url: '/organization/:orgId/settings', - templateUrl: 'app/organization/views/organizationSettings.html', - controller: 'organizationSettingsController', - data: { pageTitle: 'Organization Settings' } - }) - .state('backend.org.billing', { - url: '/organization/:orgId/billing', - templateUrl: 'app/organization/views/organizationBilling.html', - controller: 'organizationBillingController', - data: { pageTitle: 'Organization Billing' } - }) - .state('backend.org.vault', { - url: '/organization/:orgId/vault?viewEvents&search', - templateUrl: 'app/organization/views/organizationVault.html', - controller: 'organizationVaultController', - data: { - pageTitle: 'Organization Vault', - controlSidebar: true - } - }) - .state('backend.org.groups', { - url: '/organization/:orgId/groups?search', - templateUrl: 'app/organization/views/organizationGroups.html', - controller: 'organizationGroupsController', - data: { pageTitle: 'Organization Groups' } - }) - .state('backend.org.events', { - url: '/organization/:orgId/events', - templateUrl: 'app/organization/views/organizationEvents.html', - controller: 'organizationEventsController', - data: { pageTitle: 'Organization Events' } - }) - - // Frontend - .state('frontend', { - templateUrl: 'app/views/frontendLayout.html', - abstract: true, - data: { - authorize: false - } - }) - .state('frontend.login', { - templateUrl: 'app/accounts/views/accountsLogin.html', - controller: 'accountsLoginController', - params: { - returnState: null, - email: null, - premium: null, - org: null - }, - data: { - bodyClass: 'login-page' - } - }) - .state('frontend.login.info', { - url: '^/?org&premium&email', - templateUrl: 'app/accounts/views/accountsLoginInfo.html', - data: { - pageTitle: 'Log In' - } - }) - .state('frontend.login.twoFactor', { - url: '^/two-step?org&premium&email', - templateUrl: 'app/accounts/views/accountsLoginTwoFactor.html', - data: { - pageTitle: 'Log In (Two-step)' - } - }) - .state('frontend.logout', { - url: '^/logout', - controller: 'accountsLogoutController', - data: { - authorize: true - } - }) - .state('frontend.passwordHint', { - url: '^/password-hint', - templateUrl: 'app/accounts/views/accountsPasswordHint.html', - controller: 'accountsPasswordHintController', - data: { - pageTitle: 'Master Password Hint', - bodyClass: 'login-page' - } - }) - .state('frontend.recover', { - url: '^/recover', - templateUrl: 'app/accounts/views/accountsRecover.html', - controller: 'accountsRecoverController', - data: { - pageTitle: 'Recover Account', - bodyClass: 'login-page' - } - }) - .state('frontend.recover-delete', { - url: '^/recover-delete', - templateUrl: 'app/accounts/views/accountsRecoverDelete.html', - controller: 'accountsRecoverDeleteController', - data: { - pageTitle: 'Delete Account', - bodyClass: 'login-page' - } - }) - .state('frontend.verify-recover-delete', { - url: '^/verify-recover-delete?userId&token&email', - templateUrl: 'app/accounts/views/accountsVerifyRecoverDelete.html', - controller: 'accountsVerifyRecoverDeleteController', - data: { - pageTitle: 'Confirm Delete Account', - bodyClass: 'login-page' - } - }) - .state('frontend.register', { - url: '^/register?org&premium', - templateUrl: 'app/accounts/views/accountsRegister.html', - controller: 'accountsRegisterController', - params: { - returnState: null, - email: null, - org: null, - premium: null - }, - data: { - pageTitle: 'Register', - bodyClass: 'register-page' - } - }) - .state('frontend.organizationAccept', { - url: '^/accept-organization?organizationId&organizationUserId&token&email&organizationName', - templateUrl: 'app/accounts/views/accountsOrganizationAccept.html', - controller: 'accountsOrganizationAcceptController', - data: { - pageTitle: 'Accept Organization Invite', - bodyClass: 'login-page', - skipAuthorize: true - } - }) - .state('frontend.verifyEmail', { - url: '^/verify-email?userId&token', - templateUrl: 'app/accounts/views/accountsVerifyEmail.html', - controller: 'accountsVerifyEmailController', - data: { - pageTitle: 'Verifying Email', - bodyClass: 'login-page', - skipAuthorize: true - } - }); - }) - .run(function ($rootScope, authService, $state) { - $rootScope.$on('$stateChangeSuccess', function () { - $('html, body').animate({ scrollTop: 0 }, 200); - }); - - $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { - if (!toState.data || !toState.data.authorize) { - if (toState.data && toState.data.skipAuthorize) { - return; - } - - if (!authService.isAuthenticated()) { - return; - } - - event.preventDefault(); - $state.go('backend.user.vault'); - return; - } - - if (!authService.isAuthenticated()) { - event.preventDefault(); - authService.logOut(); - $state.go('frontend.login.info'); - return; - } - - // user is guaranteed to be authenticated becuase of previous check - if (toState.name.indexOf('backend.org.') > -1 && toParams.orgId) { - // clear vault rootScope when visiting org admin section - $rootScope.vaultCiphers = $rootScope.vaultFolders = $rootScope.vaultCollections = null; - - authService.getUserProfile().then(function (profile) { - var orgs = profile.organizations; - if (!orgs || !(toParams.orgId in orgs) || orgs[toParams.orgId].status !== 2 || - orgs[toParams.orgId].type === 2) { - event.preventDefault(); - $state.go('backend.user.vault'); - } - }); - } - }); - }); \ No newline at end of file diff --git a/src/app/constants.js b/src/app/constants.js deleted file mode 100644 index 24797a403d..0000000000 --- a/src/app/constants.js +++ /dev/null @@ -1,220 +0,0 @@ -angular.module('bit') - .constant('constants', { - rememberedEmailCookieName: 'bit.rememberedEmail', - encType: { - AesCbc256_B64: 0, - AesCbc128_HmacSha256_B64: 1, - AesCbc256_HmacSha256_B64: 2, - Rsa2048_OaepSha256_B64: 3, - Rsa2048_OaepSha1_B64: 4, - Rsa2048_OaepSha256_HmacSha256_B64: 5, - Rsa2048_OaepSha1_HmacSha256_B64: 6 - }, - orgUserType: { - owner: 0, - admin: 1, - user: 2 - }, - orgUserStatus: { - invited: 0, - accepted: 1, - confirmed: 2 - }, - twoFactorProvider: { - u2f: 4, - yubikey: 3, - duo: 2, - authenticator: 0, - email: 1, - remember: 5, - organizationDuo: 6 - }, - cipherType: { - login: 1, - secureNote: 2, - card: 3, - identity: 4 - }, - fieldType: { - text: 0, - hidden: 1, - boolean: 2 - }, - deviceType: { - android: 0, - ios: 1, - chromeExt: 2, - firefoxExt: 3, - operaExt: 4, - edgeExt: 5, - windowsDesktop: 6, - macOsDesktop: 7, - linuxDesktop: 8, - chrome: 9, - firefox: 10, - opera: 11, - edge: 12, - ie: 13, - unknown: 14, - uwp: 16, - safari: 17, - vivaldi: 18, - vivaldiExt: 19 - }, - eventType: { - User_LoggedIn: 1000, - User_ChangedPassword: 1001, - User_Enabled2fa: 1002, - User_Disabled2fa: 1003, - User_Recovered2fa: 1004, - User_FailedLogIn: 1005, - User_FailedLogIn2fa: 1006, - - Cipher_Created: 1100, - Cipher_Updated: 1101, - Cipher_Deleted: 1102, - Cipher_AttachmentCreated: 1103, - Cipher_AttachmentDeleted: 1104, - Cipher_Shared: 1105, - Cipher_UpdatedCollections: 1106, - - Collection_Created: 1300, - Collection_Updated: 1301, - Collection_Deleted: 1302, - - Group_Created: 1400, - Group_Updated: 1401, - Group_Deleted: 1402, - - OrganizationUser_Invited: 1500, - OrganizationUser_Confirmed: 1501, - OrganizationUser_Updated: 1502, - OrganizationUser_Removed: 1503, - OrganizationUser_UpdatedGroups: 1504, - - Organization_Updated: 1600 - }, - twoFactorProviderInfo: [ - { - type: 0, - name: 'Authenticator App', - description: 'Use an authenticator app (such as Authy or Google Authenticator) to generate time-based ' + - 'verification codes.', - enabled: false, - active: true, - free: true, - image: 'authapp.png', - displayOrder: 0, - priority: 1, - requiresUsb: false, - organization: false - }, - { - type: 3, - name: 'YubiKey OTP Security Key', - description: 'Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices.', - enabled: false, - active: true, - image: 'yubico.png', - displayOrder: 1, - priority: 3, - requiresUsb: true, - organization: false - }, - { - type: 2, - name: 'Duo', - description: 'Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.', - enabled: false, - active: true, - image: 'duo.png', - displayOrder: 2, - priority: 2, - requiresUsb: false, - organization: false - }, - { - type: 4, - name: 'FIDO U2F Security Key', - description: 'Use any FIDO U2F enabled security key to access your account.', - enabled: false, - active: true, - image: 'fido.png', - displayOrder: 3, - priority: 4, - requiresUsb: true, - organization: false - }, - { - type: 1, - name: 'Email', - description: 'Verification codes will be emailed to you.', - enabled: false, - active: true, - free: true, - image: 'gmail.png', - displayOrder: 4, - priority: 0, - requiresUsb: false, - organization: false - }, - { - type: 6, - name: 'Duo (Organization)', - description: 'Verify with Duo Security for your organization using the Duo Mobile app, SMS, ' + - 'phone call, or U2F security key.', - enabled: false, - active: true, - image: 'duo.png', - displayOrder: 1, - priority: 10, - requiresUsb: false, - organization: true - } - ], - plans: { - free: { - basePrice: 0, - noAdditionalSeats: true, - noPayment: true, - upgradeSortOrder: -1 - }, - families: { - basePrice: 1, - annualBasePrice: 12, - baseSeats: 5, - noAdditionalSeats: true, - annualPlanType: 'familiesAnnually', - upgradeSortOrder: 1 - }, - teams: { - basePrice: 5, - annualBasePrice: 60, - monthlyBasePrice: 8, - baseSeats: 5, - seatPrice: 2, - annualSeatPrice: 24, - monthlySeatPrice: 2.5, - monthPlanType: 'teamsMonthly', - annualPlanType: 'teamsAnnually', - upgradeSortOrder: 2 - }, - enterprise: { - seatPrice: 3, - annualSeatPrice: 36, - monthlySeatPrice: 4, - monthPlanType: 'enterpriseMonthly', - annualPlanType: 'enterpriseAnnually', - upgradeSortOrder: 3 - } - }, - storageGb: { - price: 0.33, - monthlyPrice: 0.50, - yearlyPrice: 4 - }, - premium: { - price: 10, - yearlyPrice: 10 - } - }); diff --git a/src/app/directives/apiFieldDirective.js b/src/app/directives/apiFieldDirective.js deleted file mode 100644 index a053712a5a..0000000000 --- a/src/app/directives/apiFieldDirective.js +++ /dev/null @@ -1,30 +0,0 @@ -angular - .module('bit.directives') - - .directive('apiField', function () { - var linkFn = function (scope, element, attrs, ngModel) { - ngModel.$registerApiError = registerApiError; - ngModel.$validators.apiValidate = apiValidator; - - function apiValidator() { - ngModel.$setValidity('api', true); - return true; - } - - function registerApiError() { - ngModel.$setValidity('api', false); - } - }; - - return { - require: 'ngModel', - restrict: 'A', - compile: function (elem, attrs) { - if (!attrs.name || attrs.name === '') { - throw 'api-field element does not have a valid name attribute'; - } - - return linkFn; - } - }; - }); \ No newline at end of file diff --git a/src/app/directives/apiFormDirective.js b/src/app/directives/apiFormDirective.js deleted file mode 100644 index b1842cf2e4..0000000000 --- a/src/app/directives/apiFormDirective.js +++ /dev/null @@ -1,45 +0,0 @@ -angular - .module('bit.directives') - - .directive('apiForm', function ($rootScope, validationService, $timeout) { - return { - require: 'form', - restrict: 'A', - link: function (scope, element, attrs, formCtrl) { - var watchPromise = attrs.apiForm || null; - if (watchPromise !== void 0) { - scope.$watch(watchPromise, formSubmitted.bind(null, formCtrl, scope)); - } - } - }; - - function formSubmitted(form, scope, promise) { - if (!promise || !promise.then) { - return; - } - - // reset errors - form.$errors = null; - - // start loading - form.$loading = true; - - promise.then(function success(response) { - $timeout(function () { - form.$loading = false; - }); - }, function failure(reason) { - $timeout(function () { - form.$loading = false; - if (typeof reason === 'string') { - validationService.addError(form, null, reason, true); - } - else { - validationService.addErrors(form, reason); - } - scope.$broadcast('show-errors-check-validity'); - $('html, body').animate({ scrollTop: 0 }, 200); - }); - }); - } - }); \ No newline at end of file diff --git a/src/app/directives/directivesModule.js b/src/app/directives/directivesModule.js deleted file mode 100644 index ad4865f131..0000000000 --- a/src/app/directives/directivesModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.directives', []); diff --git a/src/app/directives/fallbackSrcDirective.js b/src/app/directives/fallbackSrcDirective.js deleted file mode 100644 index 1df1015e71..0000000000 --- a/src/app/directives/fallbackSrcDirective.js +++ /dev/null @@ -1,11 +0,0 @@ -angular - .module('bit.directives') - - .directive('fallbackSrc', function () { - return function (scope, element, attrs) { - var el = $(element); - el.bind('error', function (event) { - el.attr('src', attrs.fallbackSrc); - }); - }; - }); diff --git a/src/app/directives/letterAvatarDirective.js b/src/app/directives/letterAvatarDirective.js deleted file mode 100644 index 774f6a184a..0000000000 --- a/src/app/directives/letterAvatarDirective.js +++ /dev/null @@ -1,151 +0,0 @@ -angular - .module('bit.directives') - - // adaptation of https://github.com/uttesh/ngletteravatar - .directive('letterAvatar', function () { - // ref: http://stackoverflow.com/a/16348977/1090359 - function stringToColor(str) { - var hash = 0, - i = 0; - for (i = 0; i < str.length; i++) { - hash = str.charCodeAt(i) + ((hash << 5) - hash); - } - - var color = '#'; - for (i = 0; i < 3; i++) { - var value = (hash >> (i * 8)) & 0xFF; - color += ('00' + value.toString(16)).substr(-2); - } - - return color; - } - - function getFirstLetters(data, count) { - var parts = data.split(' '); - if (parts && parts.length > 1) { - var text = ''; - for (var i = 0; i < count; i++) { - text += parts[i].substr(0, 1); - } - return text; - } - - return null; - } - - function getSvg(width, height, color) { - var svgTag = angular.element('') - .attr({ - 'xmlns': 'http://www.w3.org/2000/svg', - 'pointer-events': 'none', - 'width': width, - 'height': height - }) - .css({ - 'background-color': color, - 'width': width + 'px', - 'height': height + 'px' - }); - - return svgTag; - } - - function getCharText(character, textColor, fontFamily, fontWeight, fontsize) { - var textTag = angular.element('') - .attr({ - 'y': '50%', - 'x': '50%', - 'dy': '0.35em', - 'pointer-events': 'auto', - 'fill': textColor, - 'font-family': fontFamily - }) - .text(character) - .css({ - 'font-weight': fontWeight, - 'font-size': fontsize + 'px', - }); - - return textTag; - } - - return { - restrict: 'AE', - replace: true, - scope: { - data: '@' - }, - link: function (scope, element, attrs) { - var params = { - charCount: attrs.charcount || 2, - data: attrs.data, - textColor: attrs.textcolor || '#ffffff', - bgColor: attrs.bgcolor, - height: attrs.avheight || 45, - width: attrs.avwidth || 45, - fontSize: attrs.fontsize || 20, - fontWeight: attrs.fontweight || 300, - fontFamily: attrs.fontfamily || 'Open Sans, HelveticaNeue-Light, Helvetica Neue Light, ' + - 'Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif', - round: attrs.round || 'true', - dynamic: attrs.dynamic || 'true', - class: attrs.avclass || '', - border: attrs.avborder || 'false', - borderStyle: attrs.borderstyle || '3px solid white' - }; - - if (params.dynamic === 'true') { - scope.$watch('data', function () { - generateLetterAvatar(); - }); - } - else { - generateLetterAvatar(); - } - - function generateLetterAvatar() { - var c = null, - upperData = scope.data.toUpperCase(); - - if (params.charCount > 1) { - c = getFirstLetters(upperData, params.charCount); - } - - if (!c) { - c = upperData.substr(0, params.charCount); - } - - var cobj = getCharText(c, params.textColor, params.fontFamily, params.fontWeight, params.fontSize); - var color = params.bgColor ? params.bgColor : stringToColor(upperData); - var svg = getSvg(params.width, params.height, color); - svg.append(cobj); - var lvcomponent = angular.element('
').append(svg).html(); - - var svgHtml = window.btoa(unescape(encodeURIComponent(lvcomponent))); - var src = 'data:image/svg+xml;base64,' + svgHtml; - - var img = angular.element('').attr({ src: src, title: scope.data }); - - if (params.round === 'true') { - img.css('border-radius', '50%'); - } - - if (params.border === 'true') { - img.css('border', params.borderStyle); - } - - if (params.class) { - img.addClass(params.class); - } - - if (params.dynamic === 'true') { - element.empty(); - element.append(img); - } - else { - element.replaceWith(img); - } - } - } - }; - }); diff --git a/src/app/directives/masterPasswordDirective.js b/src/app/directives/masterPasswordDirective.js deleted file mode 100644 index f80d6d7c73..0000000000 --- a/src/app/directives/masterPasswordDirective.js +++ /dev/null @@ -1,38 +0,0 @@ -angular - .module('bit.directives') - - .directive('masterPassword', function (cryptoService, authService) { - return { - require: 'ngModel', - restrict: 'A', - link: function (scope, elem, attr, ngModel) { - authService.getUserProfile().then(function (profile) { - // For DOM -> model validation - ngModel.$parsers.unshift(function (value) { - if (!value) { - return undefined; - } - - return cryptoService.makeKey(value, profile.email).then(function (result) { - var valid = result.keyB64 === cryptoService.getKey().keyB64; - ngModel.$setValidity('masterPassword', valid); - return valid ? value : undefined; - }); - }); - - // For model -> DOM validation - ngModel.$formatters.unshift(function (value) { - if (!value) { - return undefined; - } - - return cryptoService.makeKey(value, profile.email).then(function (result) { - var valid = result.keyB64 === cryptoService.getKey().keyB64; - ngModel.$setValidity('masterPassword', valid); - return value; - }); - }); - }); - } - }; - }); \ No newline at end of file diff --git a/src/app/directives/pageTitleDirective.js b/src/app/directives/pageTitleDirective.js deleted file mode 100644 index a5fc2bdd5e..0000000000 --- a/src/app/directives/pageTitleDirective.js +++ /dev/null @@ -1,22 +0,0 @@ -angular - .module('bit.directives') - - .directive('pageTitle', function ($rootScope, $timeout, appSettings) { - return { - link: function (scope, element) { - var listener = function (event, toState, toParams, fromState, fromParams) { - // Default title - var title = 'Bitwarden Web Vault'; - if (toState.data && toState.data.pageTitle) { - title = toState.data.pageTitle + ' - ' + title; - } - - $timeout(function () { - element.text(title); - }); - }; - - $rootScope.$on('$stateChangeStart', listener); - } - }; - }); \ No newline at end of file diff --git a/src/app/directives/passwordMeterDirective.js b/src/app/directives/passwordMeterDirective.js deleted file mode 100644 index 15b6e86fcd..0000000000 --- a/src/app/directives/passwordMeterDirective.js +++ /dev/null @@ -1,73 +0,0 @@ -angular - .module('bit.directives') - - .directive('passwordMeter', function () { - return { - template: '
{{value}}%
', - restrict: 'A', - scope: { - password: '=passwordMeter', - username: '=passwordMeterUsername', - outerClass: '@?' - }, - link: function (scope) { - var measureStrength = function (username, password) { - if (!password || password === username) { - return 0; - } - - var strength = password.length; - - if (username && username !== '') { - if (username.indexOf(password) !== -1) strength -= 15; - if (password.indexOf(username) !== -1) strength -= username.length; - } - - if (password.length > 0 && password.length <= 4) strength += password.length; - else if (password.length >= 5 && password.length <= 7) strength += 6; - else if (password.length >= 8 && password.length <= 15) strength += 12; - else if (password.length >= 16) strength += 18; - - if (password.match(/[a-z]/)) strength += 1; - if (password.match(/[A-Z]/)) strength += 5; - if (password.match(/\d/)) strength += 5; - if (password.match(/.*\d.*\d.*\d/)) strength += 5; - if (password.match(/[!,@,#,$,%,^,&,*,?,_,~]/)) strength += 5; - if (password.match(/.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~]/)) strength += 5; - if (password.match(/(?=.*[a-z])(?=.*[A-Z])/)) strength += 2; - if (password.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/)) strength += 2; - if (password.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!,@,#,$,%,^,&,*,?,_,~])/)) strength += 2; - - strength = Math.round(strength * 2); - return Math.max(0, Math.min(100, strength)); - }; - - var getClass = function (strength) { - switch (Math.round(strength / 33)) { - case 0: - case 1: - return 'danger'; - case 2: - return 'warning'; - case 3: - return 'success'; - } - }; - - var updateMeter = function (scope) { - scope.value = measureStrength(scope.username, scope.password); - scope.valueClass = getClass(scope.value); - }; - - scope.$watch('password', function () { - updateMeter(scope); - }); - - scope.$watch('username', function () { - updateMeter(scope); - }); - }, - }; - }); diff --git a/src/app/directives/passwordViewerDirective.js b/src/app/directives/passwordViewerDirective.js deleted file mode 100644 index 67f3626733..0000000000 --- a/src/app/directives/passwordViewerDirective.js +++ /dev/null @@ -1,27 +0,0 @@ -angular - .module('bit.directives') - - .directive('passwordViewer', function () { - return { - restrict: 'A', - link: function (scope, element, attr) { - var passwordViewer = attr.passwordViewer; - if (!passwordViewer) { - return; - } - - element.onclick = function (event) { }; - element.on('click', function (event) { - var passwordElement = $(passwordViewer); - if (passwordElement && passwordElement.attr('type') === 'password') { - element.removeClass('fa-eye').addClass('fa-eye-slash'); - passwordElement.attr('type', 'text'); - } - else if (passwordElement && passwordElement.attr('type') === 'text') { - element.removeClass('fa-eye-slash').addClass('fa-eye'); - passwordElement.attr('type', 'password'); - } - }); - } - }; - }); diff --git a/src/app/directives/stopClickDirective.js b/src/app/directives/stopClickDirective.js deleted file mode 100644 index edbcbe62c9..0000000000 --- a/src/app/directives/stopClickDirective.js +++ /dev/null @@ -1,11 +0,0 @@ -angular - .module('bit.directives') - - // ref: https://stackoverflow.com/a/14165848/1090359 - .directive('stopClick', function () { - return function (scope, element, attrs) { - $(element).click(function (event) { - event.preventDefault(); - }); - }; - }); diff --git a/src/app/directives/stopPropDirective.js b/src/app/directives/stopPropDirective.js deleted file mode 100644 index 5b0f606029..0000000000 --- a/src/app/directives/stopPropDirective.js +++ /dev/null @@ -1,10 +0,0 @@ -angular - .module('bit.directives') - - .directive('stopProp', function () { - return function (scope, element, attrs) { - $(element).click(function (event) { - event.stopPropagation(); - }); - }; - }); diff --git a/src/app/directives/totpDirective.js b/src/app/directives/totpDirective.js deleted file mode 100644 index 965c924ed6..0000000000 --- a/src/app/directives/totpDirective.js +++ /dev/null @@ -1,193 +0,0 @@ -angular - .module('bit.directives') - - .directive('totp', function ($timeout, $q) { - return { - template: '
' + - '{{sec}}' + - '' + - '' + - '{{codeFormatted}}' + - '' + - '' + - '
', - restrict: 'A', - scope: { - key: '=totp' - }, - link: function (scope) { - var interval = null; - - var Totp = function () { - var b32Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; - - var leftpad = function (s, l, p) { - if (l + 1 >= s.length) { - s = Array(l + 1 - s.length).join(p) + s; - } - return s; - }; - - var dec2hex = function (d) { - return (d < 15.5 ? '0' : '') + Math.round(d).toString(16); - }; - - var hex2dec = function (s) { - return parseInt(s, 16); - }; - - var hex2bytes = function (s) { - var bytes = new Uint8Array(s.length / 2); - for (var i = 0; i < s.length; i += 2) { - bytes[i / 2] = parseInt(s.substr(i, 2), 16); - } - return bytes; - }; - - var buff2hex = function (buff) { - var bytes = new Uint8Array(buff); - var hex = []; - for (var i = 0; i < bytes.length; i++) { - hex.push((bytes[i] >>> 4).toString(16)); - hex.push((bytes[i] & 0xF).toString(16)); - } - return hex.join(''); - }; - - var b32tohex = function (s) { - s = s.toUpperCase(); - var cleanedInput = ''; - var i; - for (i = 0; i < s.length; i++) { - if (b32Chars.indexOf(s[i]) < 0) { - continue; - } - - cleanedInput += s[i]; - } - s = cleanedInput; - - var bits = ''; - var hex = ''; - for (i = 0; i < s.length; i++) { - var byteIndex = b32Chars.indexOf(s.charAt(i)); - if (byteIndex < 0) { - continue; - } - bits += leftpad(byteIndex.toString(2), 5, '0'); - } - for (i = 0; i + 4 <= bits.length; i += 4) { - var chunk = bits.substr(i, 4); - hex = hex + parseInt(chunk, 2).toString(16); - } - return hex; - }; - - var b32tobytes = function (s) { - return hex2bytes(b32tohex(s)); - }; - - var sign = function (keyBytes, timeBytes) { - return window.crypto.subtle.importKey('raw', keyBytes, - { name: 'HMAC', hash: { name: 'SHA-1' } }, false, ['sign']).then(function (key) { - return window.crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-1' } }, key, timeBytes); - }).then(function (signature) { - return buff2hex(signature); - }).catch(function (err) { - return null; - }); - }; - - this.getCode = function (keyb32) { - var epoch = Math.round(new Date().getTime() / 1000.0); - var timeHex = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0'); - var timeBytes = hex2bytes(timeHex); - var keyBytes = b32tobytes(keyb32); - - if (!keyBytes.length || !timeBytes.length) { - return $q(function (resolve, reject) { - resolve(null); - }); - } - - return sign(keyBytes, timeBytes).then(function (hashHex) { - if (!hashHex) { - return null; - } - - var offset = hex2dec(hashHex.substring(hashHex.length - 1)); - var otp = (hex2dec(hashHex.substr(offset * 2, 8)) & hex2dec('7fffffff')) + ''; - otp = (otp).substr(otp.length - 6, 6); - return otp; - }); - }; - }; - - var totp = new Totp(); - - var updateCode = function (scope) { - totp.getCode(scope.key).then(function (code) { - $timeout(function () { - if (code) { - scope.codeFormatted = code.substring(0, 3) + ' ' + code.substring(3); - scope.code = code; - } - else { - scope.code = null; - if (interval) { - clearInterval(interval); - } - } - }); - }); - }; - - var tick = function (scope) { - $timeout(function () { - var epoch = Math.round(new Date().getTime() / 1000.0); - var mod = epoch % 30; - var sec = 30 - mod; - - scope.sec = sec; - scope.dash = (2.62 * mod).toFixed(2); - scope.low = sec <= 7; - if (mod === 0) { - updateCode(scope); - } - }); - }; - - scope.$watch('key', function () { - if (!scope.key) { - scope.code = null; - if (interval) { - clearInterval(interval); - } - return; - } - - updateCode(scope); - tick(scope); - - if (interval) { - clearInterval(interval); - } - - interval = setInterval(function () { - tick(scope); - }, 1000); - }); - - scope.$on('$destroy', function () { - if (interval) { - clearInterval(interval); - } - }); - - scope.clipboardError = function (e) { - alert('Your web browser does not support easy clipboard copying.'); - }; - }, - }; - }); diff --git a/src/app/dummy.module.ts b/src/app/dummy.module.ts new file mode 100644 index 0000000000..62b7969531 --- /dev/null +++ b/src/app/dummy.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; + +import { ModalComponent } from 'jslib/angular/components/modal.component'; + +@NgModule({ + imports: [], + declarations: [ + ModalComponent, + ], +}) +export class DummyModule { +} diff --git a/src/app/filters/enumLabelClassFilter.js b/src/app/filters/enumLabelClassFilter.js deleted file mode 100644 index 84a5d57bf9..0000000000 --- a/src/app/filters/enumLabelClassFilter.js +++ /dev/null @@ -1,32 +0,0 @@ -angular - .module('bit.filters') - - .filter('enumLabelClass', function () { - return function (input, name) { - if (typeof input !== 'number') { - return input.toString(); - } - - var output; - switch (name) { - case 'OrgUserStatus': - switch (input) { - case 0: - output = 'label-default'; - break; - case 1: - output = 'label-warning'; - break; - case 2: - /* falls through */ - default: - output = 'label-success'; - } - break; - default: - output = 'label-default'; - } - - return output; - }; - }); diff --git a/src/app/filters/enumNameFilter.js b/src/app/filters/enumNameFilter.js deleted file mode 100644 index 5678c49766..0000000000 --- a/src/app/filters/enumNameFilter.js +++ /dev/null @@ -1,46 +0,0 @@ -angular - .module('bit.filters') - - .filter('enumName', function () { - return function (input, name) { - if (typeof input !== 'number') { - return input.toString(); - } - - var output; - switch (name) { - case 'OrgUserStatus': - switch (input) { - case 0: - output = 'Invited'; - break; - case 1: - output = 'Accepted'; - break; - case 2: - /* falls through */ - default: - output = 'Confirmed'; - } - break; - case 'OrgUserType': - switch (input) { - case 0: - output = 'Owner'; - break; - case 1: - output = 'Admin'; - break; - case 2: - /* falls through */ - default: - output = 'User'; - } - break; - default: - output = input.toString(); - } - - return output; - }; - }); diff --git a/src/app/filters/filtersModule.js b/src/app/filters/filtersModule.js deleted file mode 100644 index 02c0dc595f..0000000000 --- a/src/app/filters/filtersModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.filters', []); diff --git a/src/app/global/globalModule.js b/src/app/global/globalModule.js deleted file mode 100644 index 9af6c4b9f8..0000000000 --- a/src/app/global/globalModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.global', []); diff --git a/src/app/global/mainController.js b/src/app/global/mainController.js deleted file mode 100644 index a6878c434a..0000000000 --- a/src/app/global/mainController.js +++ /dev/null @@ -1,187 +0,0 @@ -angular - .module('bit.global') - - .controller('mainController', function ($scope, $state, authService, appSettings, toastr, $window, $document, - cryptoService, $uibModal, apiService) { - var vm = this; - vm.skinClass = appSettings.selfHosted ? 'skin-blue-light' : 'skin-blue'; - vm.bodyClass = ''; - vm.usingControlSidebar = vm.openControlSidebar = false; - vm.searchVaultText = null; - vm.version = appSettings.version; - vm.outdatedBrowser = $window.navigator.userAgent.indexOf('MSIE') !== -1 || - $window.navigator.userAgent.indexOf('SamsungBrowser') !== -1; - - $scope.currentYear = new Date().getFullYear(); - - $scope.$on('$viewContentLoaded', function () { - authService.getUserProfile().then(function (profile) { - vm.userProfile = profile; - }); - - if ($.AdminLTE) { - if ($.AdminLTE.layout) { - $.AdminLTE.layout.fix(); - $.AdminLTE.layout.fixSidebar(); - } - - if ($.AdminLTE.pushMenu) { - $.AdminLTE.pushMenu.expandOnHover(); - } - - $document.off('click', '.sidebar li a'); - } - }); - - $scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { - vm.usingEncKey = !!cryptoService.getEncKey(); - vm.searchVaultText = null; - - if (toState.data.bodyClass) { - vm.bodyClass = toState.data.bodyClass; - return; - } - else { - vm.bodyClass = ''; - } - - vm.usingControlSidebar = !!toState.data.controlSidebar; - vm.openControlSidebar = vm.usingControlSidebar && $document.width() > 768; - }); - - $scope.addCipher = function () { - $scope.$broadcast('vaultAddCipher'); - }; - - $scope.addFolder = function () { - $scope.$broadcast('vaultAddFolder'); - }; - - $scope.addOrganizationCipher = function () { - $scope.$broadcast('organizationVaultAddCipher'); - }; - - $scope.addOrganizationCollection = function () { - $scope.$broadcast('organizationCollectionsAdd'); - }; - - $scope.inviteOrganizationUser = function () { - $scope.$broadcast('organizationPeopleInvite'); - }; - - $scope.addOrganizationGroup = function () { - $scope.$broadcast('organizationGroupsAdd'); - }; - - $scope.updateKey = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsUpdateKey.html', - controller: 'settingsUpdateKeyController' - }); - }; - - $scope.verifyEmail = function () { - if ($scope.sendingVerify) { - return; - } - - $scope.sendingVerify = true; - apiService.accounts.verifyEmail({}, null).$promise.then(function () { - toastr.success('Verification email sent.'); - $scope.sendingVerify = false; - $scope.verifyEmailSent = true; - }).catch(function () { - toastr.success('Verification email failed.'); - $scope.sendingVerify = false; - }); - }; - - $scope.updateBrowser = function () { - $window.open('https://browser-update.org/update.html', '_blank'); - }; - - // Append dropdown menu somewhere else - var bodyScrollbarWidth, - appendedDropdownMenu, - appendedDropdownMenuParent; - - var dropdownHelpers = { - scrollbarWidth: function () { - if (!bodyScrollbarWidth) { - var bodyElem = $('body'); - bodyElem.addClass('bit-position-body-scrollbar-measure'); - bodyScrollbarWidth = $window.innerWidth - bodyElem[0].clientWidth; - bodyScrollbarWidth = isFinite(bodyScrollbarWidth) ? bodyScrollbarWidth : 0; - bodyElem.removeClass('bit-position-body-scrollbar-measure'); - } - - return bodyScrollbarWidth; - }, - scrollbarInfo: function () { - return { - width: dropdownHelpers.scrollbarWidth(), - visible: $document.height() > $($window).height() - }; - } - }; - - $(window).on('show.bs.dropdown', function (e) { - /*jshint -W120 */ - var target = appendedDropdownMenuParent = $(e.target); - - var appendTo = target.data('appendTo'); - if (!appendTo) { - return true; - } - - appendedDropdownMenu = target.find('.dropdown-menu'); - var appendToEl = $(appendTo); - appendToEl.append(appendedDropdownMenu.detach()); - - var offset = target.offset(); - var css = { - display: 'block', - top: offset.top + target.outerHeight() - (appendTo !== 'body' ? $(window).scrollTop() : 0) - }; - - if (appendedDropdownMenu.hasClass('dropdown-menu-right')) { - var scrollbarInfo = dropdownHelpers.scrollbarInfo(); - var scrollbarWidth = 0; - if (scrollbarInfo.visible && scrollbarInfo.width) { - scrollbarWidth = scrollbarInfo.width; - } - - css.right = $window.innerWidth - scrollbarWidth - (offset.left + target.prop('offsetWidth')) + 'px'; - css.left = 'auto'; - } - else { - css.left = offset.left + 'px'; - css.right = 'auto'; - } - - appendedDropdownMenu.css(css); - }); - - $(window).on('hide.bs.dropdown', function (e) { - if (!appendedDropdownMenu) { - return true; - } - - $(e.target).append(appendedDropdownMenu.detach()); - appendedDropdownMenu.hide(); - appendedDropdownMenu = null; - appendedDropdownMenuParent = null; - }); - - $scope.$on('removeAppendedDropdownMenu', function (event, args) { - if (!appendedDropdownMenu && !appendedDropdownMenuParent) { - return true; - } - - appendedDropdownMenuParent.append(appendedDropdownMenu.detach()); - appendedDropdownMenu.hide(); - appendedDropdownMenu = null; - appendedDropdownMenuParent = null; - }); - }); diff --git a/src/app/global/paidOrgRequiredController.js b/src/app/global/paidOrgRequiredController.js deleted file mode 100644 index e303d5428c..0000000000 --- a/src/app/global/paidOrgRequiredController.js +++ /dev/null @@ -1,26 +0,0 @@ -angular - .module('bit.global') - - .controller('paidOrgRequiredController', function ($scope, $state, $uibModalInstance, $analytics, $uibModalStack, orgId, - constants, authService) { - $analytics.eventTrack('paidOrgRequiredController', { category: 'Modal' }); - - authService.getUserProfile().then(function (profile) { - $scope.admin = profile.organizations[orgId].type !== constants.orgUserType.user; - }); - - $scope.go = function () { - if (!$scope.admin) { - return; - } - - $analytics.eventTrack('Get Paid Org'); - $state.go('backend.org.billing', { orgId: orgId }).then(function () { - $uibModalStack.dismissAll(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - }); diff --git a/src/app/global/premiumRequiredController.js b/src/app/global/premiumRequiredController.js deleted file mode 100644 index 9b870eb8d6..0000000000 --- a/src/app/global/premiumRequiredController.js +++ /dev/null @@ -1,17 +0,0 @@ -angular - .module('bit.global') - - .controller('premiumRequiredController', function ($scope, $state, $uibModalInstance, $analytics, $uibModalStack) { - $analytics.eventTrack('premiumRequiredController', { category: 'Modal' }); - - $scope.go = function () { - $analytics.eventTrack('Get Premium'); - $state.go('backend.user.settingsPremium').then(function () { - $uibModalStack.dismissAll(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - }); diff --git a/src/app/global/sideNavController.js b/src/app/global/sideNavController.js deleted file mode 100644 index 287e60d626..0000000000 --- a/src/app/global/sideNavController.js +++ /dev/null @@ -1,57 +0,0 @@ -angular - .module('bit.global') - - .controller('sideNavController', function ($scope, $state, authService, toastr, $analytics, constants, appSettings) { - $scope.$state = $state; - $scope.params = $state.params; - $scope.orgs = []; - $scope.name = ''; - - if(appSettings.selfHosted) { - $scope.orgIconBgColor = '#ffffff'; - $scope.orgIconBorder = '3px solid #a0a0a0'; - $scope.orgIconTextColor = '#333333'; - } - else { - $scope.orgIconBgColor = '#2c3b41'; - $scope.orgIconBorder = '3px solid #1a2226'; - $scope.orgIconTextColor = '#ffffff'; - } - - authService.getUserProfile().then(function (userProfile) { - $scope.name = userProfile.extended && userProfile.extended.name ? - userProfile.extended.name : userProfile.email; - - if (!userProfile.organizations) { - return; - } - - if ($state.includes('backend.org') && ($state.params.orgId in userProfile.organizations)) { - $scope.orgProfile = userProfile.organizations[$state.params.orgId]; - } - else { - var orgs = []; - for (var orgId in userProfile.organizations) { - if (userProfile.organizations.hasOwnProperty(orgId) && - (userProfile.organizations[orgId].enabled || userProfile.organizations[orgId].type < 2)) { // 2 = User - orgs.push(userProfile.organizations[orgId]); - } - } - $scope.orgs = orgs; - } - }); - - $scope.viewOrganization = function (org) { - if (org.type === constants.orgUserType.user) { - toastr.error('You cannot manage this organization.'); - return; - } - - $analytics.eventTrack('View Organization From Side Nav'); - $state.go('backend.org.dashboard', { orgId: org.id }); - }; - - $scope.isOrgOwner = function (org) { - return org && org.type === constants.orgUserType.owner; - }; - }); diff --git a/src/app/global/topNavController.js b/src/app/global/topNavController.js deleted file mode 100644 index 521f9b5d4e..0000000000 --- a/src/app/global/topNavController.js +++ /dev/null @@ -1,14 +0,0 @@ -angular - .module('bit.global') - - .controller('topNavController', function ($scope) { - $scope.toggleControlSidebar = function () { - var bod = $('body'); - if (!bod.hasClass('control-sidebar-open')) { - bod.addClass('control-sidebar-open'); - } - else { - bod.removeClass('control-sidebar-open'); - } - }; - }); diff --git a/src/app/layouts/footer.component.html b/src/app/layouts/footer.component.html new file mode 100644 index 0000000000..d8e28c86d9 --- /dev/null +++ b/src/app/layouts/footer.component.html @@ -0,0 +1,13 @@ + diff --git a/src/app/layouts/footer.component.ts b/src/app/layouts/footer.component.ts new file mode 100644 index 0000000000..e545d60bcc --- /dev/null +++ b/src/app/layouts/footer.component.ts @@ -0,0 +1,20 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +@Component({ + selector: 'app-footer', + templateUrl: 'footer.component.html', +}) +export class FooterComponent implements OnInit { + version: string; + + constructor(private platformUtilsService: PlatformUtilsService) { } + + ngOnInit() { + this.version = this.platformUtilsService.getApplicationVersion(); + } +} diff --git a/src/app/layouts/frontend-layout.component.html b/src/app/layouts/frontend-layout.component.html new file mode 100644 index 0000000000..4b6b96523b --- /dev/null +++ b/src/app/layouts/frontend-layout.component.html @@ -0,0 +1,5 @@ + +
+ © 2018, 8bit Solutions LLC +
{{'versionNumber' | i18n : version}} +
diff --git a/src/app/layouts/frontend-layout.component.ts b/src/app/layouts/frontend-layout.component.ts new file mode 100644 index 0000000000..8510c1bc0e --- /dev/null +++ b/src/app/layouts/frontend-layout.component.ts @@ -0,0 +1,26 @@ +import { + Component, + OnDestroy, + OnInit, +} from '@angular/core'; + +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +@Component({ + selector: 'app-frontend-layout', + templateUrl: 'frontend-layout.component.html', +}) +export class FrontendLayoutComponent implements OnInit, OnDestroy { + version: string; + + constructor(private platformUtilsService: PlatformUtilsService) { } + + ngOnInit() { + this.version = this.platformUtilsService.getApplicationVersion(); + document.body.classList.add('layout_frontend'); + } + + ngOnDestroy() { + document.body.classList.remove('layout_frontend'); + } +} diff --git a/src/app/layouts/navbar.component.html b/src/app/layouts/navbar.component.html new file mode 100644 index 0000000000..ea541eb399 --- /dev/null +++ b/src/app/layouts/navbar.component.html @@ -0,0 +1,58 @@ + diff --git a/src/app/layouts/navbar.component.ts b/src/app/layouts/navbar.component.ts new file mode 100644 index 0000000000..19d3cda3e9 --- /dev/null +++ b/src/app/layouts/navbar.component.ts @@ -0,0 +1,37 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { MessagingService } from 'jslib/abstractions/messaging.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { TokenService } from 'jslib/abstractions/token.service'; + +@Component({ + selector: 'app-navbar', + templateUrl: 'navbar.component.html', +}) +export class NavbarComponent implements OnInit { + selfHosted = false; + name: string; + + constructor(private messagingService: MessagingService, private platformUtilsService: PlatformUtilsService, + private tokenService: TokenService) { + this.selfHosted = this.platformUtilsService.isSelfHost(); + } + + async ngOnInit() { + this.name = await this.tokenService.getName(); + if (this.name == null || this.name.trim() === '') { + this.name = await this.tokenService.getEmail(); + } + } + + lock() { + this.messagingService.send('lockVault'); + } + + logOut() { + this.messagingService.send('logout'); + } +} diff --git a/src/app/layouts/organization-layout.component.html b/src/app/layouts/organization-layout.component.html new file mode 100644 index 0000000000..70246ad104 --- /dev/null +++ b/src/app/layouts/organization-layout.component.html @@ -0,0 +1,40 @@ + +
+
+
+ +
+ {{organization.name}} + {{'organization' | i18n}} +
+
+ +
+
+ + diff --git a/src/app/layouts/organization-layout.component.ts b/src/app/layouts/organization-layout.component.ts new file mode 100644 index 0000000000..792cf613ae --- /dev/null +++ b/src/app/layouts/organization-layout.component.ts @@ -0,0 +1,33 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { UserService } from 'jslib/abstractions/user.service'; + +import { Organization } from 'jslib/models/domain/organization'; + +@Component({ + selector: 'app-organization-layout', + templateUrl: 'organization-layout.component.html', +}) +export class OrganizationLayoutComponent implements OnInit { + organization: Organization; + + private organizationId: string; + + constructor(private route: ActivatedRoute, private userService: UserService) { } + + ngOnInit() { + document.body.classList.remove('layout_frontend'); + this.route.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + await this.load(); + }); + } + + async load() { + this.organization = await this.userService.getOrganization(this.organizationId); + } +} diff --git a/src/app/layouts/user-layout.component.html b/src/app/layouts/user-layout.component.html new file mode 100644 index 0000000000..28dca81162 --- /dev/null +++ b/src/app/layouts/user-layout.component.html @@ -0,0 +1,3 @@ + + + diff --git a/src/app/layouts/user-layout.component.ts b/src/app/layouts/user-layout.component.ts new file mode 100644 index 0000000000..503a270794 --- /dev/null +++ b/src/app/layouts/user-layout.component.ts @@ -0,0 +1,14 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +@Component({ + selector: 'app-user-layout', + templateUrl: 'user-layout.component.html', +}) +export class UserLayoutComponent implements OnInit { + ngOnInit() { + document.body.classList.remove('layout_frontend'); + } +} diff --git a/src/app/main.ts b/src/app/main.ts new file mode 100644 index 0000000000..23ad91fa6d --- /dev/null +++ b/src/app/main.ts @@ -0,0 +1,17 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import 'bootstrap'; +import 'jquery'; +import 'popper.js'; + +// tslint:disable-next-line +require('../scss/styles.scss'); + +import { AppModule } from './app.module'; + +if (process.env.ENV === 'production') { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/src/app/modal.component.ts b/src/app/modal.component.ts new file mode 100644 index 0000000000..aef1f4f7ea --- /dev/null +++ b/src/app/modal.component.ts @@ -0,0 +1,63 @@ +import * as jq from 'jquery'; + +import { + Component, + ComponentFactoryResolver, + Type, + ViewContainerRef, +} from '@angular/core'; + +import { ModalComponent as BaseModalComponent } from 'jslib/angular/components/modal.component'; + +@Component({ + selector: 'app-modal', + template: ``, +}) +export class ModalComponent extends BaseModalComponent { + el: any = null; + + constructor(componentFactoryResolver: ComponentFactoryResolver) { + super(componentFactoryResolver); + } + + ngOnDestroy() { /* Nothing */ } + + show(type: Type, parentContainer: ViewContainerRef, fade: boolean = true): T { + this.parentContainer = parentContainer; + this.fade = fade; + + const factory = this.componentFactoryResolver.resolveComponentFactory(type); + const componentRef = this.container.createComponent(factory); + + const modals = Array.from(document.querySelectorAll('.modal')); + if (modals.length > 0) { + this.el = jq(modals[0]); + this.el.modal('show'); + + this.el.on('show.bs.modal', () => { + this.onShow.emit(); + }); + this.el.on('shown.bs.modal', () => { + this.onShown.emit(); + this.el.find('*[appAutoFocus]').focus(); + }); + this.el.on('hide.bs.modal', () => { + this.onClose.emit(); + }); + this.el.on('hidden.bs.modal', () => { + this.onClosed.emit(); + if (this.parentContainer != null) { + this.parentContainer.clear(); + } + }); + } + + return componentRef.instance; + } + + close() { + if (this.el != null) { + this.el.modal('hide'); + } + } +} diff --git a/src/app/organization/organizationBillingAdjustSeatsController.js b/src/app/organization/organizationBillingAdjustSeatsController.js deleted file mode 100644 index 8aa31d15c9..0000000000 --- a/src/app/organization/organizationBillingAdjustSeatsController.js +++ /dev/null @@ -1,37 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingAdjustSeatsController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, add) { - $analytics.eventTrack('organizationBillingAdjustSeatsController', { category: 'Modal' }); - $scope.add = add; - $scope.seatAdjustment = 0; - - $scope.submit = function () { - var request = { - seatAdjustment: $scope.seatAdjustment - }; - - if (!add) { - request.seatAdjustment *= -1; - } - - $scope.submitPromise = apiService.organizations.putSeat({ id: $state.params.orgId }, request) - .$promise.then(function (response) { - if (add) { - $analytics.eventTrack('Added Seats'); - toastr.success('You have added ' + $scope.seatAdjustment + ' seats.'); - } - else { - $analytics.eventTrack('Removed Seats'); - toastr.success('You have removed ' + $scope.seatAdjustment + ' seats.'); - } - - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationBillingAdjustStorageController.js b/src/app/organization/organizationBillingAdjustStorageController.js deleted file mode 100644 index 7363da1b84..0000000000 --- a/src/app/organization/organizationBillingAdjustStorageController.js +++ /dev/null @@ -1,37 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingAdjustStorageController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, add) { - $analytics.eventTrack('organizationBillingAdjustStorageController', { category: 'Modal' }); - $scope.add = add; - $scope.storageAdjustment = 0; - - $scope.submit = function () { - var request = { - storageGbAdjustment: $scope.storageAdjustment - }; - - if (!add) { - request.storageGbAdjustment *= -1; - } - - $scope.submitPromise = apiService.organizations.putStorage({ id: $state.params.orgId }, request) - .$promise.then(function (response) { - if (add) { - $analytics.eventTrack('Added Organization Storage'); - toastr.success('You have added ' + $scope.storageAdjustment + ' GB.'); - } - else { - $analytics.eventTrack('Removed Organization Storage'); - toastr.success('You have removed ' + $scope.storageAdjustment + ' GB.'); - } - - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationBillingChangePaymentController.js b/src/app/organization/organizationBillingChangePaymentController.js deleted file mode 100644 index 8b31b0452c..0000000000 --- a/src/app/organization/organizationBillingChangePaymentController.js +++ /dev/null @@ -1,64 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingChangePaymentController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, existingPaymentMethod - // @if !selfHosted - /* jshint ignore:start */ - , stripe - /* jshint ignore:end */ - // @endif - ) { - $analytics.eventTrack('organizationBillingChangePaymentController', { category: 'Modal' }); - $scope.existingPaymentMethod = existingPaymentMethod; - $scope.paymentMethod = 'card'; - $scope.showPaymentOptions = true; - $scope.hidePaypal = true; - $scope.card = {}; - $scope.bank = {}; - - $scope.changePaymentMethod = function (val) { - $scope.paymentMethod = val; - }; - - $scope.submit = function () { - var stripeReq = null; - if ($scope.paymentMethod === 'card') { - stripeReq = stripe.card.createToken($scope.card); - } - else if ($scope.paymentMethod === 'bank') { - $scope.bank.currency = 'USD'; - $scope.bank.country = 'US'; - stripeReq = stripe.bankAccount.createToken($scope.bank); - } - else { - return; - } - - $scope.submitPromise = stripeReq.then(function (response) { - var request = { - paymentToken: response.id - }; - - return apiService.organizations.putPayment({ id: $state.params.orgId }, request).$promise; - }, function (err) { - throw err.message; - }).then(function (response) { - $scope.card = null; - if (existingPaymentMethod) { - $analytics.eventTrack('Changed Organization Payment Method'); - toastr.success('You have changed your payment method.'); - } - else { - $analytics.eventTrack('Added Organization Payment Method'); - toastr.success('You have added a payment method.'); - } - - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationBillingChangePlanController.js b/src/app/organization/organizationBillingChangePlanController.js deleted file mode 100644 index bf587a57a1..0000000000 --- a/src/app/organization/organizationBillingChangePlanController.js +++ /dev/null @@ -1,14 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingChangePlanController', function ($scope, $state, apiService, $uibModalInstance, - toastr, $analytics) { - $analytics.eventTrack('organizationBillingChangePlanController', { category: 'Modal' }); - $scope.submit = function () { - - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationBillingController.js b/src/app/organization/organizationBillingController.js deleted file mode 100644 index 88c09f5f82..0000000000 --- a/src/app/organization/organizationBillingController.js +++ /dev/null @@ -1,305 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingController', function ($scope, apiService, $state, $uibModal, toastr, $analytics, - appSettings, tokenService, $window) { - $scope.selfHosted = appSettings.selfHosted; - $scope.charges = []; - $scope.paymentSource = null; - $scope.plan = null; - $scope.subscription = null; - $scope.loading = true; - var license = null; - $scope.expiration = null; - - $scope.$on('$viewContentLoaded', function () { - load(); - }); - - $scope.changePayment = function () { - if ($scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsBillingChangePayment.html', - controller: 'organizationBillingChangePaymentController', - resolve: { - existingPaymentMethod: function () { - return $scope.paymentSource ? $scope.paymentSource.description : null; - } - } - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.changePlan = function () { - if ($scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationBillingChangePlan.html', - controller: 'organizationBillingChangePlanController', - resolve: { - plan: function () { - return $scope.plan; - } - } - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.adjustSeats = function (add) { - if ($scope.selfHosted || !$scope.canAdjustSeats) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationBillingAdjustSeats.html', - controller: 'organizationBillingAdjustSeatsController', - resolve: { - add: function () { - return add; - } - } - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.adjustStorage = function (add) { - if ($scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsBillingAdjustStorage.html', - controller: 'organizationBillingAdjustStorageController', - resolve: { - add: function () { - return add; - } - } - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.verifyBank = function () { - if ($scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationBillingVerifyBank.html', - controller: 'organizationBillingVerifyBankController' - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.cancel = function () { - if ($scope.selfHosted) { - return; - } - - if (!confirm('Are you sure you want to cancel? All users will lose access to the organization ' + - 'at the end of this billing cycle.')) { - return; - } - - apiService.organizations.putCancel({ id: $state.params.orgId }, {}) - .$promise.then(function (response) { - $analytics.eventTrack('Canceled Plan'); - toastr.success('Organization subscription has been canceled.'); - load(); - }); - }; - - $scope.reinstate = function () { - if ($scope.selfHosted) { - return; - } - - if (!confirm('Are you sure you want to remove the cancellation request and reinstate this organization?')) { - return; - } - - apiService.organizations.putReinstate({ id: $state.params.orgId }, {}) - .$promise.then(function (response) { - $analytics.eventTrack('Reinstated Plan'); - toastr.success('Organization cancellation request has been removed.'); - load(); - }); - }; - - $scope.updateLicense = function () { - if (!$scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsBillingUpdateLicense.html', - controller: 'organizationBillingUpdateLicenseController' - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.license = function () { - if ($scope.selfHosted) { - return; - } - - var installationId = prompt("Enter your installation id"); - if (!installationId || installationId === '') { - return; - } - - apiService.organizations.getLicense({ - id: $state.params.orgId, - installationId: installationId - }, function (license) { - var licenseString = JSON.stringify(license, null, 2); - var licenseBlob = new Blob([licenseString]); - - // IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx - if (window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveBlob(licenseBlob, 'bitwarden_organization_license.json'); - } - else { - var a = window.document.createElement('a'); - a.href = window.URL.createObjectURL(licenseBlob, { type: 'text/plain' }); - a.download = 'bitwarden_organization_license.json'; - document.body.appendChild(a); - // IE: "Access is denied". - // ref: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access - a.click(); - document.body.removeChild(a); - } - }, function (err) { - if (err.status === 400) { - toastr.error("Invalid installation id."); - } - else { - toastr.error("Unable to generate license."); - } - }); - }; - - $scope.viewInvoice = function (charge) { - if ($scope.selfHosted) { - return; - } - var url = appSettings.apiUri + '/organizations/' + $state.params.orgId + - '/billing-invoice/' + charge.invoiceId + '?access_token=' + tokenService.getToken(); - $window.open(url); - }; - - function load() { - apiService.organizations.getBilling({ id: $state.params.orgId }, function (org) { - $scope.loading = false; - $scope.noSubscription = org.PlanType === 0; - $scope.canAdjustSeats = org.PlanType > 1; - - var i = 0; - $scope.expiration = org.Expiration; - license = org.License; - - $scope.plan = { - name: org.Plan, - type: org.PlanType, - seats: org.Seats - }; - - $scope.storage = null; - if ($scope && org.MaxStorageGb) { - $scope.storage = { - currentGb: org.StorageGb || 0, - maxGb: org.MaxStorageGb, - currentName: org.StorageName || '0 GB' - }; - - $scope.storage.percentage = +(100 * ($scope.storage.currentGb / $scope.storage.maxGb)).toFixed(2); - } - - $scope.subscription = null; - if (org.Subscription) { - $scope.subscription = { - trialEndDate: org.Subscription.TrialEndDate, - cancelledDate: org.Subscription.CancelledDate, - status: org.Subscription.Status, - cancelled: org.Subscription.Cancelled, - markedForCancel: !org.Subscription.Cancelled && org.Subscription.CancelAtEndDate - }; - } - - $scope.nextInvoice = null; - if (org.UpcomingInvoice) { - $scope.nextInvoice = { - date: org.UpcomingInvoice.Date, - amount: org.UpcomingInvoice.Amount - }; - } - - if (org.Subscription && org.Subscription.Items) { - $scope.subscription.items = []; - for (i = 0; i < org.Subscription.Items.length; i++) { - $scope.subscription.items.push({ - amount: org.Subscription.Items[i].Amount, - name: org.Subscription.Items[i].Name, - interval: org.Subscription.Items[i].Interval, - qty: org.Subscription.Items[i].Quantity - }); - } - } - - $scope.paymentSource = null; - if (org.PaymentSource) { - $scope.paymentSource = { - type: org.PaymentSource.Type, - description: org.PaymentSource.Description, - cardBrand: org.PaymentSource.CardBrand, - needsVerification: org.PaymentSource.NeedsVerification - }; - } - - var charges = []; - for (i = 0; i < org.Charges.length; i++) { - charges.push({ - date: org.Charges[i].CreatedDate, - paymentSource: org.Charges[i].PaymentSource ? org.Charges[i].PaymentSource.Description : '-', - amount: org.Charges[i].Amount, - status: org.Charges[i].Status, - failureMessage: org.Charges[i].FailureMessage, - refunded: org.Charges[i].Refunded, - partiallyRefunded: org.Charges[i].PartiallyRefunded, - refundedAmount: org.Charges[i].RefundedAmount, - invoiceId: org.Charges[i].InvoiceId - }); - } - $scope.charges = charges; - }); - } - }); diff --git a/src/app/organization/organizationBillingUpdateLicenseController.js b/src/app/organization/organizationBillingUpdateLicenseController.js deleted file mode 100644 index 0b8d3ba2a7..0000000000 --- a/src/app/organization/organizationBillingUpdateLicenseController.js +++ /dev/null @@ -1,30 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingUpdateLicenseController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, validationService) { - $analytics.eventTrack('organizationBillingUpdateLicenseController', { category: 'Modal' }); - - $scope.submit = function (form) { - var fileEl = document.getElementById('file'); - var files = fileEl.files; - if (!files || !files.length) { - validationService.addError(form, 'file', 'Select a license file.', true); - return; - } - - var fd = new FormData(); - fd.append('license', files[0]); - - $scope.submitPromise = apiService.organizations.putLicense({ id: $state.params.orgId }, fd) - .$promise.then(function (response) { - $analytics.eventTrack('Updated License'); - toastr.success('You have updated your license.'); - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationBillingVerifyBankController.js b/src/app/organization/organizationBillingVerifyBankController.js deleted file mode 100644 index 9489ebbc58..0000000000 --- a/src/app/organization/organizationBillingVerifyBankController.js +++ /dev/null @@ -1,25 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationBillingVerifyBankController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr) { - $analytics.eventTrack('organizationBillingVerifyBankController', { category: 'Modal' }); - - $scope.submit = function () { - var request = { - amount1: $scope.amount1, - amount2: $scope.amount2 - }; - - $scope.submitPromise = apiService.organizations.postVerifyBank({ id: $state.params.orgId }, request) - .$promise.then(function (response) { - $analytics.eventTrack('Verified Bank Account'); - toastr.success('You have successfully verified your bank account.'); - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationCollectionsAddController.js b/src/app/organization/organizationCollectionsAddController.js deleted file mode 100644 index a8516a9775..0000000000 --- a/src/app/organization/organizationCollectionsAddController.js +++ /dev/null @@ -1,120 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationCollectionsAddController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - $analytics, authService) { - $analytics.eventTrack('organizationCollectionsAddController', { category: 'Modal' }); - var groupsLength = 0; - $scope.groups = []; - $scope.selectedGroups = {}; - $scope.loading = true; - $scope.useGroups = false; - - $uibModalInstance.opened.then(function () { - return authService.getUserProfile(); - }).then(function (profile) { - if (profile.organizations) { - var org = profile.organizations[$state.params.orgId]; - $scope.useGroups = !!org.useGroups; - } - - if ($scope.useGroups) { - return apiService.groups.listOrganization({ orgId: $state.params.orgId }).$promise; - } - - return null; - }).then(function (groups) { - if (!groups) { - $scope.loading = false; - return; - } - - var groupsArr = []; - for (var i = 0; i < groups.Data.length; i++) { - groupsArr.push({ - id: groups.Data[i].Id, - name: groups.Data[i].Name, - accessAll: groups.Data[i].AccessAll - }); - - if (!groups.Data[i].AccessAll) { - groupsLength++; - } - } - - $scope.groups = groupsArr; - $scope.loading = false; - }); - - $scope.toggleGroupSelectionAll = function ($event) { - var groups = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.groups.length; i++) { - groups[$scope.groups[i].id] = { - id: $scope.groups[i].id, - readOnly: ($scope.groups[i].id in $scope.selectedGroups) ? - $scope.selectedGroups[$scope.groups[i].id].readOnly : false - }; - } - } - - $scope.selectedGroups = groups; - }; - - $scope.toggleGroupSelection = function (id) { - if (id in $scope.selectedGroups) { - delete $scope.selectedGroups[id]; - } - else { - $scope.selectedGroups[id] = { - id: id, - readOnly: false - }; - } - }; - - $scope.toggleGroupReadOnlySelection = function (group) { - if (group.id in $scope.selectedGroups) { - $scope.selectedGroups[group.id].readOnly = !group.accessAll && !!!$scope.selectedGroups[group.id].readOnly; - } - }; - - $scope.groupSelected = function (group) { - return group.id in $scope.selectedGroups || group.accessAll; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedGroups).length >= groupsLength; - }; - - $scope.submit = function (model) { - var collection = cipherService.encryptCollection(model, $state.params.orgId); - - if ($scope.useGroups) { - collection.groups = []; - - for (var groupId in $scope.selectedGroups) { - if ($scope.selectedGroups.hasOwnProperty(groupId)) { - for (var i = 0; i < $scope.groups.length; i++) { - if ($scope.groups[i].id === $scope.selectedGroups[groupId].id) { - if (!$scope.groups[i].accessAll) { - collection.groups.push($scope.selectedGroups[groupId]); - } - break; - } - } - } - } - } - - $scope.submitPromise = apiService.collections.post({ orgId: $state.params.orgId }, collection, function (response) { - $analytics.eventTrack('Created Collection'); - var decCollection = cipherService.decryptCollection(response, $state.params.orgId, true); - $uibModalInstance.close(decCollection); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationCollectionsController.js b/src/app/organization/organizationCollectionsController.js deleted file mode 100644 index 880d3932e5..0000000000 --- a/src/app/organization/organizationCollectionsController.js +++ /dev/null @@ -1,107 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationCollectionsController', function ($scope, $state, apiService, $uibModal, cipherService, $filter, - toastr, $analytics, $uibModalStack) { - $scope.collections = []; - $scope.loading = true; - $scope.$on('$viewContentLoaded', function () { - loadList(); - }); - - $scope.$on('organizationCollectionsAdd', function (event, args) { - $scope.add(); - }); - - $scope.add = function () { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationCollectionsAdd.html', - controller: 'organizationCollectionsAddController' - }); - - modal.result.then(function (collection) { - $scope.collections.push(collection); - }); - }; - - $scope.edit = function (collection) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationCollectionsEdit.html', - controller: 'organizationCollectionsEditController', - resolve: { - id: function () { return collection.id; } - } - }); - - modal.result.then(function (editedCollection) { - var existingCollections = $filter('filter')($scope.collections, { id: editedCollection.id }, true); - if (existingCollections && existingCollections.length > 0) { - existingCollections[0].name = editedCollection.name; - } - }); - }; - - $scope.users = function (collection) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationCollectionsUsers.html', - controller: 'organizationCollectionsUsersController', - size: 'lg', - resolve: { - collection: function () { return collection; } - } - }); - - modal.result.then(function () { - // nothing to do - }); - }; - - $scope.groups = function (collection) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationCollectionsGroups.html', - controller: 'organizationCollectionsGroupsController', - resolve: { - collection: function () { return collection; } - } - }); - - modal.result.then(function () { - // nothing to do - }); - }; - - $scope.delete = function (collection) { - if (!confirm('Are you sure you want to delete this collection (' + collection.name + ')?')) { - return; - } - - apiService.collections.del({ orgId: $state.params.orgId, id: collection.id }, function () { - var index = $scope.collections.indexOf(collection); - if (index > -1) { - $scope.collections.splice(index, 1); - } - - $analytics.eventTrack('Deleted Collection'); - toastr.success(collection.name + ' has been deleted.', 'Collection Deleted'); - }, function () { - toastr.error(collection.name + ' was not able to be deleted.', 'Error'); - }); - }; - - function loadList() { - apiService.collections.listOrganization({ orgId: $state.params.orgId }, function (list) { - $scope.collections = cipherService.decryptCollections(list.Data, $state.params.orgId, true); - $scope.loading = false; - - if ($state.params.search) { - $uibModalStack.dismissAll(); - $scope.filterSearch = $state.params.search; - $('#filterSearch').focus(); - } - }); - } - }); diff --git a/src/app/organization/organizationCollectionsEditController.js b/src/app/organization/organizationCollectionsEditController.js deleted file mode 100644 index 26bb0f224c..0000000000 --- a/src/app/organization/organizationCollectionsEditController.js +++ /dev/null @@ -1,139 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationCollectionsEditController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - $analytics, id, authService) { - $analytics.eventTrack('organizationCollectionsEditController', { category: 'Modal' }); - var groupsLength = 0; - $scope.collection = {}; - $scope.groups = []; - $scope.selectedGroups = {}; - $scope.loading = true; - $scope.useGroups = false; - - $uibModalInstance.opened.then(function () { - return apiService.collections.getDetails({ orgId: $state.params.orgId, id: id }).$promise; - }).then(function (collection) { - $scope.collection = cipherService.decryptCollection(collection); - - var groups = {}; - if (collection.Groups) { - for (var i = 0; i < collection.Groups.length; i++) { - groups[collection.Groups[i].Id] = { - id: collection.Groups[i].Id, - readOnly: collection.Groups[i].ReadOnly - }; - } - } - $scope.selectedGroups = groups; - - return authService.getUserProfile(); - }).then(function (profile) { - if (profile.organizations) { - var org = profile.organizations[$state.params.orgId]; - $scope.useGroups = !!org.useGroups; - } - - if ($scope.useGroups) { - return apiService.groups.listOrganization({ orgId: $state.params.orgId }).$promise; - } - - return null; - }).then(function (groups) { - if (!groups) { - $scope.loading = false; - return; - } - - var groupsArr = []; - for (var i = 0; i < groups.Data.length; i++) { - groupsArr.push({ - id: groups.Data[i].Id, - name: groups.Data[i].Name, - accessAll: groups.Data[i].AccessAll - }); - - if (!groups.Data[i].AccessAll) { - groupsLength++; - } - } - - $scope.groups = groupsArr; - $scope.loading = false; - }); - - $scope.toggleGroupSelectionAll = function ($event) { - var groups = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.groups.length; i++) { - groups[$scope.groups[i].id] = { - id: $scope.groups[i].id, - readOnly: ($scope.groups[i].id in $scope.selectedGroups) ? - $scope.selectedGroups[$scope.groups[i].id].readOnly : false - }; - } - } - - $scope.selectedGroups = groups; - }; - - $scope.toggleGroupSelection = function (id) { - if (id in $scope.selectedGroups) { - delete $scope.selectedGroups[id]; - } - else { - $scope.selectedGroups[id] = { - id: id, - readOnly: false - }; - } - }; - - $scope.toggleGroupReadOnlySelection = function (group) { - if (group.id in $scope.selectedGroups) { - $scope.selectedGroups[group.id].readOnly = !group.accessAll && !!!$scope.selectedGroups[group.id].readOnly; - } - }; - - $scope.groupSelected = function (group) { - return group.id in $scope.selectedGroups || group.accessAll; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedGroups).length >= groupsLength; - }; - - $scope.submit = function (model) { - var collection = cipherService.encryptCollection(model, $state.params.orgId); - - if ($scope.useGroups) { - collection.groups = []; - - for (var groupId in $scope.selectedGroups) { - if ($scope.selectedGroups.hasOwnProperty(groupId)) { - for (var i = 0; i < $scope.groups.length; i++) { - if ($scope.groups[i].id === $scope.selectedGroups[groupId].id) { - if (!$scope.groups[i].accessAll) { - collection.groups.push($scope.selectedGroups[groupId]); - } - break; - } - } - } - } - } - - $scope.submitPromise = apiService.collections.put({ - orgId: $state.params.orgId, - id: id - }, collection, function (response) { - $analytics.eventTrack('Edited Collection'); - var decCollection = cipherService.decryptCollection(response, $state.params.orgId, true); - $uibModalInstance.close(decCollection); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationCollectionsUsersController.js b/src/app/organization/organizationCollectionsUsersController.js deleted file mode 100644 index 7b230671df..0000000000 --- a/src/app/organization/organizationCollectionsUsersController.js +++ /dev/null @@ -1,63 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationCollectionsUsersController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - $analytics, collection, toastr) { - $analytics.eventTrack('organizationCollectionsUsersController', { category: 'Modal' }); - $scope.loading = true; - $scope.collection = collection; - $scope.users = []; - - $uibModalInstance.opened.then(function () { - $scope.loading = false; - apiService.collections.listUsers( - { - orgId: $state.params.orgId, - id: collection.id - }, - function (userList) { - if (userList && userList.Data.length) { - var users = []; - for (var i = 0; i < userList.Data.length; i++) { - users.push({ - organizationUserId: userList.Data[i].OrganizationUserId, - name: userList.Data[i].Name, - email: userList.Data[i].Email, - type: userList.Data[i].Type, - status: userList.Data[i].Status, - readOnly: userList.Data[i].ReadOnly, - accessAll: userList.Data[i].AccessAll - }); - } - $scope.users = users; - } - }); - }); - - $scope.remove = function (user) { - if (!confirm('Are you sure you want to remove this user (' + user.email + ') from this ' + - 'collection (' + collection.name + ')?')) { - return; - } - - apiService.collections.delUser( - { - orgId: $state.params.orgId, - id: collection.id, - orgUserId: user.organizationUserId - }, null, function () { - toastr.success(user.email + ' has been removed.', 'User Removed'); - $analytics.eventTrack('Removed User From Collection'); - var index = $scope.users.indexOf(user); - if (index > -1) { - $scope.users.splice(index, 1); - } - }, function () { - toastr.error('Unable to remove user.', 'Error'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationDashboardController.js b/src/app/organization/organizationDashboardController.js deleted file mode 100644 index 2ad7f5f755..0000000000 --- a/src/app/organization/organizationDashboardController.js +++ /dev/null @@ -1,19 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationDashboardController', function ($scope, authService, $state, appSettings) { - $scope.selfHosted = appSettings.selfHosted; - - $scope.$on('$viewContentLoaded', function () { - authService.getUserProfile().then(function (userProfile) { - if (!userProfile.organizations) { - return; - } - $scope.orgProfile = userProfile.organizations[$state.params.orgId]; - }); - }); - - $scope.goBilling = function () { - $state.go('backend.org.billing', { orgId: $state.params.orgId }); - }; - }); diff --git a/src/app/organization/organizationDeleteController.js b/src/app/organization/organizationDeleteController.js deleted file mode 100644 index 9ec087814a..0000000000 --- a/src/app/organization/organizationDeleteController.js +++ /dev/null @@ -1,25 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationDeleteController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics) { - $analytics.eventTrack('organizationDeleteController', { category: 'Modal' }); - $scope.submit = function () { - $scope.submitPromise = cryptoService.hashPassword($scope.masterPassword).then(function (hash) { - return apiService.organizations.del({ id: $state.params.orgId }, { - masterPasswordHash: hash - }).$promise; - }).then(function () { - $uibModalInstance.dismiss('cancel'); - authService.removeProfileOrganization($state.params.orgId); - $analytics.eventTrack('Deleted Organization'); - return $state.go('backend.user.vault'); - }).then(function () { - toastr.success('This organization and all associated data has been deleted.', 'Organization Deleted'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationEventsController.js b/src/app/organization/organizationEventsController.js deleted file mode 100644 index 9857cb933a..0000000000 --- a/src/app/organization/organizationEventsController.js +++ /dev/null @@ -1,100 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationEventsController', function ($scope, $state, apiService, $uibModal, $filter, - toastr, $analytics, constants, eventService, $compile, $sce) { - $scope.events = []; - $scope.orgUsers = []; - $scope.loading = true; - $scope.continuationToken = null; - - var defaultFilters = eventService.getDefaultDateFilters(); - $scope.filterStart = defaultFilters.start; - $scope.filterEnd = defaultFilters.end; - - $scope.$on('$viewContentLoaded', function () { - load(); - }); - - $scope.refresh = function () { - loadEvents(true); - }; - - $scope.next = function () { - loadEvents(false); - }; - - var i = 0, - orgUsersUserIdDict = {}, - orgUsersIdDict = {}; - - function load() { - apiService.organizationUsers.list({ orgId: $state.params.orgId }).$promise.then(function (list) { - var users = []; - for (i = 0; i < list.Data.length; i++) { - var user = { - id: list.Data[i].Id, - userId: list.Data[i].UserId, - name: list.Data[i].Name, - email: list.Data[i].Email - }; - - users.push(user); - - var displayName = user.name || user.email; - orgUsersUserIdDict[user.userId] = displayName; - orgUsersIdDict[user.id] = displayName; - } - - $scope.orgUsers = users; - - return loadEvents(true); - }); - } - - function loadEvents(clearExisting) { - var filterResult = eventService.formatDateFilters($scope.filterStart, $scope.filterEnd); - if (filterResult.error) { - alert(filterResult.error); - return; - } - - if (clearExisting) { - $scope.continuationToken = null; - $scope.events = []; - } - - $scope.loading = true; - return apiService.events.listOrganization({ - orgId: $state.params.orgId, - start: filterResult.start, - end: filterResult.end, - continuationToken: $scope.continuationToken - }).$promise.then(function (list) { - $scope.continuationToken = list.ContinuationToken; - - var events = []; - for (i = 0; i < list.Data.length; i++) { - var userId = list.Data[i].ActingUserId || list.Data[i].UserId; - var eventInfo = eventService.getEventInfo(list.Data[i]); - var htmlMessage = $compile('' + eventInfo.message + '')($scope); - events.push({ - message: $sce.trustAsHtml(htmlMessage[0].outerHTML), - appIcon: eventInfo.appIcon, - appName: eventInfo.appName, - userId: userId, - userName: userId ? (orgUsersUserIdDict[userId] || '-') : '-', - date: list.Data[i].Date, - ip: list.Data[i].IpAddress - }); - } - if ($scope.events && $scope.events.length > 0) { - $scope.events = $scope.events.concat(events); - } - else { - $scope.events = events; - } - $scope.loading = false; - }); - } - }); diff --git a/src/app/organization/organizationGroupsAddController.js b/src/app/organization/organizationGroupsAddController.js deleted file mode 100644 index 8d0bf03140..0000000000 --- a/src/app/organization/organizationGroupsAddController.js +++ /dev/null @@ -1,87 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationGroupsAddController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - $analytics) { - $analytics.eventTrack('organizationGroupsAddController', { category: 'Modal' }); - $scope.collections = []; - $scope.selectedCollections = {}; - $scope.loading = true; - - $uibModalInstance.opened.then(function () { - return apiService.collections.listOrganization({ orgId: $state.params.orgId }).$promise; - }).then(function (collections) { - $scope.collections = cipherService.decryptCollections(collections.Data, $state.params.orgId, true); - $scope.loading = false; - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - collections[$scope.collections[i].id] = { - id: $scope.collections[i].id, - readOnly: ($scope.collections[i].id in $scope.selectedCollections) ? - $scope.selectedCollections[$scope.collections[i].id].readOnly : false - }; - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = { - id: id, - readOnly: false - }; - } - }; - - $scope.toggleCollectionReadOnlySelection = function (id) { - if (id in $scope.selectedCollections) { - $scope.selectedCollections[id].readOnly = !!!$scope.selectedCollections[id].readOnly; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedCollections).length === $scope.collections.length; - }; - - $scope.submit = function (model) { - var group = { - name: model.name, - accessAll: !!model.accessAll, - externalId: model.externalId - }; - - if (!group.accessAll) { - group.collections = []; - for (var collectionId in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(collectionId)) { - group.collections.push($scope.selectedCollections[collectionId]); - } - } - } - - $scope.submitPromise = apiService.groups.post({ orgId: $state.params.orgId }, group, function (response) { - $analytics.eventTrack('Created Group'); - $uibModalInstance.close({ - id: response.Id, - name: response.Name - }); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationGroupsController.js b/src/app/organization/organizationGroupsController.js deleted file mode 100644 index 7ff81d217b..0000000000 --- a/src/app/organization/organizationGroupsController.js +++ /dev/null @@ -1,99 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationGroupsController', function ($scope, $state, apiService, $uibModal, $filter, - toastr, $analytics, $uibModalStack) { - $scope.groups = []; - $scope.loading = true; - $scope.$on('$viewContentLoaded', function () { - loadList(); - }); - - $scope.$on('organizationGroupsAdd', function (event, args) { - $scope.add(); - }); - - $scope.add = function () { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationGroupsAdd.html', - controller: 'organizationGroupsAddController' - }); - - modal.result.then(function (group) { - $scope.groups.push(group); - }); - }; - - $scope.edit = function (group) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationGroupsEdit.html', - controller: 'organizationGroupsEditController', - resolve: { - id: function () { return group.id; } - } - }); - - modal.result.then(function (editedGroup) { - var existingGroups = $filter('filter')($scope.groups, { id: editedGroup.id }, true); - if (existingGroups && existingGroups.length > 0) { - existingGroups[0].name = editedGroup.name; - } - }); - }; - - $scope.users = function (group) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationGroupsUsers.html', - controller: 'organizationGroupsUsersController', - size: 'lg', - resolve: { - group: function () { return group; } - } - }); - - modal.result.then(function () { - // nothing to do - }); - }; - - $scope.delete = function (group) { - if (!confirm('Are you sure you want to delete this group (' + group.name + ')?')) { - return; - } - - apiService.groups.del({ orgId: $state.params.orgId, id: group.id }, function () { - var index = $scope.groups.indexOf(group); - if (index > -1) { - $scope.groups.splice(index, 1); - } - - $analytics.eventTrack('Deleted Group'); - toastr.success(group.name + ' has been deleted.', 'Group Deleted'); - }, function () { - toastr.error(group.name + ' was not able to be deleted.', 'Error'); - }); - }; - - function loadList() { - apiService.groups.listOrganization({ orgId: $state.params.orgId }, function (list) { - var groups = []; - for (var i = 0; i < list.Data.length; i++) { - groups.push({ - id: list.Data[i].Id, - name: list.Data[i].Name - }); - } - $scope.groups = groups; - $scope.loading = false; - - if ($state.params.search) { - $uibModalStack.dismissAll(); - $scope.filterSearch = $state.params.search; - $('#filterSearch').focus(); - } - }); - } - }); diff --git a/src/app/organization/organizationGroupsEditController.js b/src/app/organization/organizationGroupsEditController.js deleted file mode 100644 index bdaaf071df..0000000000 --- a/src/app/organization/organizationGroupsEditController.js +++ /dev/null @@ -1,110 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationGroupsEditController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - $analytics, id) { - $analytics.eventTrack('organizationGroupsEditController', { category: 'Modal' }); - $scope.collections = []; - $scope.selectedCollections = {}; - $scope.loading = true; - - $uibModalInstance.opened.then(function () { - return apiService.groups.getDetails({ orgId: $state.params.orgId, id: id }).$promise; - }).then(function (group) { - $scope.group = { - id: id, - name: group.Name, - externalId: group.ExternalId, - accessAll: group.AccessAll - }; - - var collections = {}; - if (group.Collections) { - for (var i = 0; i < group.Collections.length; i++) { - collections[group.Collections[i].Id] = { - id: group.Collections[i].Id, - readOnly: group.Collections[i].ReadOnly - }; - } - } - $scope.selectedCollections = collections; - - return apiService.collections.listOrganization({ orgId: $state.params.orgId }).$promise; - }).then(function (collections) { - $scope.collections = cipherService.decryptCollections(collections.Data, $state.params.orgId, true); - $scope.loading = false; - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - collections[$scope.collections[i].id] = { - id: $scope.collections[i].id, - readOnly: ($scope.collections[i].id in $scope.selectedCollections) ? - $scope.selectedCollections[$scope.collections[i].id].readOnly : false - }; - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = { - id: id, - readOnly: false - }; - } - }; - - $scope.toggleCollectionReadOnlySelection = function (id) { - if (id in $scope.selectedCollections) { - $scope.selectedCollections[id].readOnly = !!!$scope.selectedCollections[id].readOnly; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedCollections).length === $scope.collections.length; - }; - - $scope.submit = function () { - var group = { - name: $scope.group.name, - accessAll: !!$scope.group.accessAll, - externalId: $scope.group.externalId - }; - - if (!group.accessAll) { - group.collections = []; - for (var collectionId in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(collectionId)) { - group.collections.push($scope.selectedCollections[collectionId]); - } - } - } - - $scope.submitPromise = apiService.groups.put({ - orgId: $state.params.orgId, - id: id - }, group, function (response) { - $analytics.eventTrack('Edited Group'); - $uibModalInstance.close({ - id: response.Id, - name: response.Name - }); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationGroupsUsersController.js b/src/app/organization/organizationGroupsUsersController.js deleted file mode 100644 index 4b3f11887e..0000000000 --- a/src/app/organization/organizationGroupsUsersController.js +++ /dev/null @@ -1,57 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationGroupsUsersController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, group, toastr) { - $analytics.eventTrack('organizationGroupUsersController', { category: 'Modal' }); - $scope.loading = true; - $scope.group = group; - $scope.users = []; - - $uibModalInstance.opened.then(function () { - return apiService.groups.listUsers({ - orgId: $state.params.orgId, - id: group.id - }).$promise; - }).then(function (userList) { - var users = []; - if (userList && userList.Data.length) { - for (var i = 0; i < userList.Data.length; i++) { - users.push({ - organizationUserId: userList.Data[i].OrganizationUserId, - name: userList.Data[i].Name, - email: userList.Data[i].Email, - type: userList.Data[i].Type, - status: userList.Data[i].Status, - accessAll: userList.Data[i].AccessAll - }); - } - } - - $scope.users = users; - $scope.loading = false; - }); - - $scope.remove = function (user) { - if (!confirm('Are you sure you want to remove this user (' + user.email + ') from this ' + - 'group (' + group.name + ')?')) { - return; - } - - apiService.groups.delUser({ orgId: $state.params.orgId, id: group.id, orgUserId: user.organizationUserId }, null, - function () { - toastr.success(user.email + ' has been removed.', 'User Removed'); - $analytics.eventTrack('Removed User From Group'); - var index = $scope.users.indexOf(user); - if (index > -1) { - $scope.users.splice(index, 1); - } - }, function () { - toastr.error('Unable to remove user.', 'Error'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationModule.js b/src/app/organization/organizationModule.js deleted file mode 100644 index 0880ae474f..0000000000 --- a/src/app/organization/organizationModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.organization', ['ui.bootstrap']); diff --git a/src/app/organization/organizationPeopleController.js b/src/app/organization/organizationPeopleController.js deleted file mode 100644 index 46195dc757..0000000000 --- a/src/app/organization/organizationPeopleController.js +++ /dev/null @@ -1,162 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationPeopleController', function ($scope, $state, $uibModal, cryptoService, apiService, authService, - toastr, $analytics, $filter, $uibModalStack) { - $scope.users = []; - $scope.useGroups = false; - $scope.useEvents = false; - - $scope.$on('$viewContentLoaded', function () { - loadList(); - - authService.getUserProfile().then(function (profile) { - if (profile.organizations) { - var org = profile.organizations[$state.params.orgId]; - $scope.useGroups = !!org.useGroups; - $scope.useEvents = !!org.useEvents; - } - }); - }); - - $scope.reinvite = function (user) { - apiService.organizationUsers.reinvite({ orgId: $state.params.orgId, id: user.id }, null, function () { - $analytics.eventTrack('Reinvited User'); - toastr.success(user.email + ' has been invited again.', 'User Invited'); - }, function () { - toastr.error('Unable to invite user.', 'Error'); - }); - }; - - $scope.delete = function (user) { - if (!confirm('Are you sure you want to remove this user (' + user.email + ')?')) { - return; - } - - apiService.organizationUsers.del({ orgId: $state.params.orgId, id: user.id }, null, function () { - $analytics.eventTrack('Deleted User'); - toastr.success(user.email + ' has been removed.', 'User Removed'); - var index = $scope.users.indexOf(user); - if (index > -1) { - $scope.users.splice(index, 1); - } - }, function () { - toastr.error('Unable to remove user.', 'Error'); - }); - }; - - $scope.confirm = function (user) { - apiService.users.getPublicKey({ id: user.userId }, function (userKey) { - var orgKey = cryptoService.getOrgKey($state.params.orgId); - if (!orgKey) { - toastr.error('Unable to confirm user.', 'Error'); - return; - } - - var key = cryptoService.rsaEncrypt(orgKey.key, userKey.PublicKey); - apiService.organizationUsers.confirm({ orgId: $state.params.orgId, id: user.id }, { key: key }, function () { - user.status = 2; - $analytics.eventTrack('Confirmed User'); - toastr.success(user.email + ' has been confirmed.', 'User Confirmed'); - }, function () { - toastr.error('Unable to confirm user.', 'Error'); - }); - }, function () { - toastr.error('Unable to confirm user.', 'Error'); - }); - }; - - $scope.$on('organizationPeopleInvite', function (event, args) { - $scope.invite(); - }); - - $scope.invite = function () { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationPeopleInvite.html', - controller: 'organizationPeopleInviteController' - }); - - modal.result.then(function () { - loadList(); - }); - }; - - $scope.edit = function (orgUser) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationPeopleEdit.html', - controller: 'organizationPeopleEditController', - resolve: { - orgUser: function () { return orgUser; } - } - }); - - modal.result.then(function () { - loadList(); - }); - }; - - $scope.groups = function (user) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationPeopleGroups.html', - controller: 'organizationPeopleGroupsController', - resolve: { - orgUser: function () { return user; } - } - }); - - modal.result.then(function () { - - }); - }; - - $scope.events = function (user) { - $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationPeopleEvents.html', - controller: 'organizationPeopleEventsController', - resolve: { - orgUser: function () { return user; }, - orgId: function () { return $state.params.orgId; } - } - }); - }; - - function loadList() { - apiService.organizationUsers.list({ orgId: $state.params.orgId }, function (list) { - var users = []; - - for (var i = 0; i < list.Data.length; i++) { - var user = { - id: list.Data[i].Id, - userId: list.Data[i].UserId, - name: list.Data[i].Name, - email: list.Data[i].Email, - status: list.Data[i].Status, - type: list.Data[i].Type, - accessAll: list.Data[i].AccessAll - }; - - users.push(user); - } - - $scope.users = users; - - if ($state.params.search) { - $uibModalStack.dismissAll(); - $scope.filterSearch = $state.params.search; - $('#filterSearch').focus(); - } - - if ($state.params.viewEvents) { - $uibModalStack.dismissAll(); - var eventUser = $filter('filter')($scope.users, { id: $state.params.viewEvents }); - if (eventUser && eventUser.length) { - $scope.events(eventUser[0]); - } - } - }); - } - }); diff --git a/src/app/organization/organizationPeopleEditController.js b/src/app/organization/organizationPeopleEditController.js deleted file mode 100644 index c35a8d3801..0000000000 --- a/src/app/organization/organizationPeopleEditController.js +++ /dev/null @@ -1,104 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationPeopleEditController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - orgUser, $analytics) { - $analytics.eventTrack('organizationPeopleEditController', { category: 'Modal' }); - - $scope.loading = true; - $scope.collections = []; - $scope.selectedCollections = {}; - - $uibModalInstance.opened.then(function () { - apiService.collections.listOrganization({ orgId: $state.params.orgId }, function (list) { - $scope.collections = cipherService.decryptCollections(list.Data, $state.params.orgId, true); - $scope.loading = false; - }); - - apiService.organizationUsers.get({ orgId: $state.params.orgId, id: orgUser.id }, function (user) { - var collections = {}; - if (user && user.Collections) { - for (var i = 0; i < user.Collections.length; i++) { - collections[user.Collections[i].Id] = { - id: user.Collections[i].Id, - readOnly: user.Collections[i].ReadOnly - }; - } - } - $scope.email = orgUser.email; - $scope.type = user.Type; - $scope.accessAll = user.AccessAll; - $scope.selectedCollections = collections; - }); - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - collections[$scope.collections[i].id] = { - id: $scope.collections[i].id, - readOnly: ($scope.collections[i].id in $scope.selectedCollections) ? - $scope.selectedCollections[$scope.collections[i].id].readOnly : false - }; - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = { - id: id, - readOnly: false - }; - } - }; - - $scope.toggleCollectionReadOnlySelection = function (id) { - if (id in $scope.selectedCollections) { - $scope.selectedCollections[id].readOnly = !!!$scope.selectedCollections[id].readOnly; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedCollections).length === $scope.collections.length; - }; - - $scope.submitPromise = null; - $scope.submit = function (model) { - var collections = []; - if (!$scope.accessAll) { - for (var collectionId in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(collectionId)) { - collections.push($scope.selectedCollections[collectionId]); - } - } - } - - $scope.submitPromise = apiService.organizationUsers.put( - { - orgId: $state.params.orgId, - id: orgUser.id - }, { - type: $scope.type, - collections: collections, - accessAll: $scope.accessAll - }, function () { - $analytics.eventTrack('Edited User'); - $uibModalInstance.close(); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationPeopleEventsController.js b/src/app/organization/organizationPeopleEventsController.js deleted file mode 100644 index 02a56936a2..0000000000 --- a/src/app/organization/organizationPeopleEventsController.js +++ /dev/null @@ -1,75 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationPeopleEventsController', function ($scope, apiService, $uibModalInstance, - orgUser, $analytics, eventService, orgId, $compile, $sce) { - $analytics.eventTrack('organizationPeopleEventsController', { category: 'Modal' }); - $scope.email = orgUser.email; - $scope.events = []; - $scope.loading = true; - $scope.continuationToken = null; - - var defaultFilters = eventService.getDefaultDateFilters(); - $scope.filterStart = defaultFilters.start; - $scope.filterEnd = defaultFilters.end; - - $uibModalInstance.opened.then(function () { - loadEvents(true); - }); - - $scope.refresh = function () { - loadEvents(true); - }; - - $scope.next = function () { - loadEvents(false); - }; - - function loadEvents(clearExisting) { - var filterResult = eventService.formatDateFilters($scope.filterStart, $scope.filterEnd); - if (filterResult.error) { - alert(filterResult.error); - return; - } - - if (clearExisting) { - $scope.continuationToken = null; - $scope.events = []; - } - - $scope.loading = true; - return apiService.events.listOrganizationUser({ - orgId: orgId, - id: orgUser.id, - start: filterResult.start, - end: filterResult.end, - continuationToken: $scope.continuationToken - }).$promise.then(function (list) { - $scope.continuationToken = list.ContinuationToken; - - var events = []; - for (var i = 0; i < list.Data.length; i++) { - var eventInfo = eventService.getEventInfo(list.Data[i]); - var htmlMessage = $compile('' + eventInfo.message + '')($scope); - events.push({ - message: $sce.trustAsHtml(htmlMessage[0].outerHTML), - appIcon: eventInfo.appIcon, - appName: eventInfo.appName, - date: list.Data[i].Date, - ip: list.Data[i].IpAddress - }); - } - if ($scope.events && $scope.events.length > 0) { - $scope.events = $scope.events.concat(events); - } - else { - $scope.events = events; - } - $scope.loading = false; - }); - } - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationPeopleGroupsController.js b/src/app/organization/organizationPeopleGroupsController.js deleted file mode 100644 index 25c9084218..0000000000 --- a/src/app/organization/organizationPeopleGroupsController.js +++ /dev/null @@ -1,85 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationPeopleGroupsController', function ($scope, $state, $uibModalInstance, apiService, - orgUser, $analytics) { - $analytics.eventTrack('organizationPeopleGroupsController', { category: 'Modal' }); - - $scope.loading = true; - $scope.groups = []; - $scope.selectedGroups = {}; - $scope.orgUser = orgUser; - - $uibModalInstance.opened.then(function () { - return apiService.groups.listOrganization({ orgId: $state.params.orgId }).$promise; - }).then(function (groupsList) { - var groups = []; - for (var i = 0; i < groupsList.Data.length; i++) { - groups.push({ - id: groupsList.Data[i].Id, - name: groupsList.Data[i].Name - }); - } - $scope.groups = groups; - - return apiService.organizationUsers.listGroups({ orgId: $state.params.orgId, id: orgUser.id }).$promise; - }).then(function (groupIds) { - var selectedGroups = {}; - if (groupIds) { - for (var i = 0; i < groupIds.length; i++) { - selectedGroups[groupIds[i]] = true; - } - } - $scope.selectedGroups = selectedGroups; - $scope.loading = false; - }); - - $scope.toggleGroupSelectionAll = function ($event) { - var groups = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.groups.length; i++) { - groups[$scope.groups[i].id] = true; - } - } - - $scope.selectedGroups = groups; - }; - - $scope.toggleGroupSelection = function (id) { - if (id in $scope.selectedGroups) { - delete $scope.selectedGroups[id]; - } - else { - $scope.selectedGroups[id] = true; - } - }; - - $scope.groupSelected = function (group) { - return group.id in $scope.selectedGroups; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedGroups).length === $scope.groups.length; - }; - - $scope.submitPromise = null; - $scope.submit = function (model) { - var groups = []; - for (var groupId in $scope.selectedGroups) { - if ($scope.selectedGroups.hasOwnProperty(groupId)) { - groups.push(groupId); - } - } - - $scope.submitPromise = apiService.organizationUsers.putGroups({ orgId: $state.params.orgId, id: orgUser.id }, { - groupIds: groups, - }, function () { - $analytics.eventTrack('Edited User Groups'); - $uibModalInstance.close(); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationPeopleInviteController.js b/src/app/organization/organizationPeopleInviteController.js deleted file mode 100644 index 80114e8261..0000000000 --- a/src/app/organization/organizationPeopleInviteController.js +++ /dev/null @@ -1,91 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationPeopleInviteController', function ($scope, $state, $uibModalInstance, apiService, cipherService, - $analytics) { - $analytics.eventTrack('organizationPeopleInviteController', { category: 'Modal' }); - - $scope.loading = true; - $scope.collections = []; - $scope.selectedCollections = {}; - $scope.model = { - type: 'User' - }; - - $uibModalInstance.opened.then(function () { - apiService.collections.listOrganization({ orgId: $state.params.orgId }, function (list) { - $scope.collections = cipherService.decryptCollections(list.Data, $state.params.orgId, true); - $scope.loading = false; - }); - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - collections[$scope.collections[i].id] = { - id: $scope.collections[i].id, - readOnly: ($scope.collections[i].id in $scope.selectedCollections) ? - $scope.selectedCollections[$scope.collections[i].id].readOnly : false - }; - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = { - id: id, - readOnly: false - }; - } - }; - - $scope.toggleCollectionReadOnlySelection = function (id) { - if (id in $scope.selectedCollections) { - $scope.selectedCollections[id].readOnly = !!!$scope.selectedCollections[id].readOnly; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedCollections).length === $scope.collections.length; - }; - - $scope.submitPromise = null; - $scope.submit = function (model) { - var collections = []; - - if (!model.accessAll) { - for (var collectionId in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(collectionId)) { - collections.push($scope.selectedCollections[collectionId]); - } - } - } - - var splitEmails = model.emails.trim().split(/\s*,\s*/); - - $scope.submitPromise = apiService.organizationUsers.invite({ orgId: $state.params.orgId }, { - emails: splitEmails, - type: model.type, - collections: collections, - accessAll: model.accessAll - }, function () { - $analytics.eventTrack('Invited User'); - $uibModalInstance.close(); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationSettingsController.js b/src/app/organization/organizationSettingsController.js deleted file mode 100644 index 1128b968d2..0000000000 --- a/src/app/organization/organizationSettingsController.js +++ /dev/null @@ -1,111 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationSettingsController', function ($scope, $state, apiService, toastr, authService, $uibModal, - $analytics, appSettings, constants, $filter) { - $scope.selfHosted = appSettings.selfHosted; - $scope.model = {}; - $scope.twoStepProviders = $filter('filter')(constants.twoFactorProviderInfo, { organization: true }); - $scope.use2fa = false; - - $scope.$on('$viewContentLoaded', function () { - apiService.organizations.get({ id: $state.params.orgId }).$promise.then(function (org) { - $scope.model = { - name: org.Name, - billingEmail: org.BillingEmail, - businessName: org.BusinessName, - businessAddress1: org.BusinessAddress1, - businessAddress2: org.BusinessAddress2, - businessAddress3: org.BusinessAddress3, - businessCountry: org.BusinessCountry, - businessTaxNumber: org.BusinessTaxNumber - }; - - $scope.use2fa = org.Use2fa; - if (org.Use2fa) { - return apiService.twoFactor.listOrganization({ orgId: $state.params.orgId }).$promise; - } - else { - return null; - } - }).then(function (response) { - if (!response || !response.Data) { - return; - } - - for (var i = 0; i < response.Data.length; i++) { - if (!response.Data[i].Enabled) { - continue; - } - - var provider = $filter('filter')($scope.twoStepProviders, { type: response.Data[i].Type }); - if (provider.length) { - provider[0].enabled = true; - } - } - }); - }); - - $scope.generalSave = function () { - if ($scope.selfHosted) { - return; - } - - $scope.generalPromise = apiService.organizations.put({ id: $state.params.orgId }, $scope.model, function (org) { - authService.updateProfileOrganization(org).then(function (updatedOrg) { - $analytics.eventTrack('Updated Organization Settings'); - toastr.success('Organization has been updated.', 'Success!'); - }); - }).$promise; - }; - - $scope.import = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/tools/views/toolsImport.html', - controller: 'organizationSettingsImportController' - }); - }; - - $scope.export = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/tools/views/toolsExport.html', - controller: 'organizationSettingsExportController' - }); - }; - - $scope.delete = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationDelete.html', - controller: 'organizationDeleteController' - }); - }; - - $scope.edit = function (provider) { - if (provider.type === constants.twoFactorProvider.organizationDuo) { - typeName = 'Duo'; - } - else { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsTwoStep' + typeName + '.html', - controller: 'settingsTwoStep' + typeName + 'Controller', - resolve: { - enabled: function () { return provider.enabled; }, - orgId: function () { return $state.params.orgId; } - } - }); - - modal.result.then(function (enabled) { - if (enabled || enabled === false) { - // do not adjust when undefined or null - provider.enabled = enabled; - } - }); - }; - }); diff --git a/src/app/organization/organizationSettingsExportController.js b/src/app/organization/organizationSettingsExportController.js deleted file mode 100644 index 1f70fbfad9..0000000000 --- a/src/app/organization/organizationSettingsExportController.js +++ /dev/null @@ -1,155 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationSettingsExportController', function ($scope, apiService, $uibModalInstance, cipherService, - $q, toastr, $analytics, $state, constants) { - $analytics.eventTrack('organizationSettingsExportController', { category: 'Modal' }); - $scope.export = function (model) { - $scope.startedExport = true; - var decCiphers = [], - decCollections = []; - - var collectionsPromise = apiService.collections.listOrganization({ orgId: $state.params.orgId }, - function (collections) { - decCollections = cipherService.decryptCollections(collections.Data, $state.params.orgId, true); - }).$promise; - - var ciphersPromise = apiService.ciphers.listOrganizationDetails({ organizationId: $state.params.orgId }, - function (ciphers) { - decCiphers = cipherService.decryptCiphers(ciphers.Data); - }).$promise; - - $q.all([collectionsPromise, ciphersPromise]).then(function () { - if (!decCiphers.length) { - toastr.error('Nothing to export.', 'Error!'); - $scope.close(); - return; - } - - var i; - var collectionsDict = {}; - for (i = 0; i < decCollections.length; i++) { - collectionsDict[decCollections[i].id] = decCollections[i]; - } - - try { - var exportCiphers = []; - for (i = 0; i < decCiphers.length; i++) { - // only export logins and secure notes - if (decCiphers[i].type !== constants.cipherType.login && - decCiphers[i].type !== constants.cipherType.secureNote) { - continue; - } - - var cipher = { - collections: [], - type: null, - name: decCiphers[i].name, - notes: decCiphers[i].notes, - fields: null, - // Login props - login_uri: null, - login_username: null, - login_password: null, - login_totp: null - }; - - var j; - if (decCiphers[i].collectionIds) { - for (j = 0; j < decCiphers[i].collectionIds.length; j++) { - if (collectionsDict.hasOwnProperty(decCiphers[i].collectionIds[j])) { - cipher.collections.push(collectionsDict[decCiphers[i].collectionIds[j]].name); - } - } - } - - if (decCiphers[i].fields) { - for (j = 0; j < decCiphers[i].fields.length; j++) { - if (!cipher.fields) { - cipher.fields = ''; - } - else { - cipher.fields += '\n'; - } - - cipher.fields += ((decCiphers[i].fields[j].name || '') + ': ' + decCiphers[i].fields[j].value); - } - } - - switch (decCiphers[i].type) { - case constants.cipherType.login: - cipher.type = 'login'; - cipher.login_uri = null; - cipher.login_username = decCiphers[i].login.username; - cipher.login_password = decCiphers[i].login.password; - cipher.login_totp = decCiphers[i].login.totp; - - if (decCiphers[i].login.uris && decCiphers[i].login.uris.length) { - cipher.login_uri = []; - for (j = 0; j < decCiphers[i].login.uris.length; j++) { - cipher.login_uri.push(decCiphers[i].login.uris[j].uri); - } - } - break; - case constants.cipherType.secureNote: - cipher.type = 'note'; - break; - default: - continue; - } - - exportCiphers.push(cipher); - } - - var csvString = Papa.unparse(exportCiphers); - var csvBlob = new Blob([csvString]); - - // IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx - if (window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveBlob(csvBlob, makeFileName()); - } - else { - var a = window.document.createElement('a'); - a.href = window.URL.createObjectURL(csvBlob, { type: 'text/plain' }); - a.download = makeFileName(); - document.body.appendChild(a); - // IE: "Access is denied". - // ref: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access - a.click(); - document.body.removeChild(a); - } - - $analytics.eventTrack('Exported Organization Data'); - toastr.success('Your data has been exported. Check your browser\'s downloads folder.', 'Success!'); - $scope.close(); - } - catch (err) { - toastr.error('Something went wrong. Please try again.', 'Error!'); - $scope.close(); - } - }, function () { - toastr.error('Something went wrong. Please try again.', 'Error!'); - $scope.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - function makeFileName() { - var now = new Date(); - var dateString = - now.getFullYear() + '' + padNumber(now.getMonth() + 1, 2) + '' + padNumber(now.getDate(), 2) + - padNumber(now.getHours(), 2) + '' + padNumber(now.getMinutes(), 2) + - padNumber(now.getSeconds(), 2); - - return 'bitwarden_org_export_' + dateString + '.csv'; - } - - function padNumber(number, width, paddingCharacter) { - paddingCharacter = paddingCharacter || '0'; - number = number + ''; - return number.length >= width ? number : new Array(width - number.length + 1).join(paddingCharacter) + number; - } - }); diff --git a/src/app/organization/organizationSettingsImportController.js b/src/app/organization/organizationSettingsImportController.js deleted file mode 100644 index 0c783446af..0000000000 --- a/src/app/organization/organizationSettingsImportController.js +++ /dev/null @@ -1,129 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationSettingsImportController', function ($scope, $state, apiService, $uibModalInstance, cipherService, - toastr, importService, $analytics, $sce, validationService, cryptoService) { - $analytics.eventTrack('organizationSettingsImportController', { category: 'Modal' }); - $scope.model = { source: '' }; - $scope.source = {}; - $scope.splitFeatured = false; - - $scope.options = [ - { - id: 'bitwardencsv', - name: 'Bitwarden (csv)', - featured: true, - sort: 1, - instructions: $sce.trustAsHtml('Export using the web vault (vault.bitwarden.com). ' + - 'Log into the web vault and navigate to your organization\'s admin area. Then to go ' + - '"Settings" > "Tools" > "Export".') - }, - { - id: 'lastpass', - name: 'LastPass (csv)', - featured: true, - sort: 2, - instructions: $sce.trustAsHtml('See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-lastpass/') - } - ]; - - $scope.setSource = function () { - for (var i = 0; i < $scope.options.length; i++) { - if ($scope.options[i].id === $scope.model.source) { - $scope.source = $scope.options[i]; - break; - } - } - }; - $scope.setSource(); - - $scope.import = function (model, form) { - if (!model.source || model.source === '') { - validationService.addError(form, 'source', 'Select the format of the import file.', true); - return; - } - - var file = document.getElementById('file').files[0]; - if (!file && (!model.fileContents || model.fileContents === '')) { - validationService.addError(form, 'file', 'Select the import file or copy/paste the import file contents.', true); - return; - } - - $scope.processing = true; - importService.importOrg(model.source, file || model.fileContents, importSuccess, importError); - }; - - function importSuccess(collections, ciphers, collectionRelationships) { - if (!collections.length && !ciphers.length) { - importError('Nothing was imported.'); - return; - } - else if (ciphers.length) { - var halfway = Math.floor(ciphers.length / 2); - var last = ciphers.length - 1; - if (cipherIsBadData(ciphers[0]) && cipherIsBadData(ciphers[halfway]) && cipherIsBadData(ciphers[last])) { - importError('Data is not formatted correctly. Please check your import file and try again.'); - return; - } - } - - apiService.ciphers.importOrg({ orgId: $state.params.orgId }, { - collections: cipherService.encryptCollections(collections, $state.params.orgId), - ciphers: cipherService.encryptCiphers(ciphers, cryptoService.getOrgKey($state.params.orgId)), - collectionRelationships: collectionRelationships - }, function () { - $uibModalInstance.dismiss('cancel'); - $state.go('backend.org.vault', { orgId: $state.params.orgId }).then(function () { - $analytics.eventTrack('Imported Org Data', { label: $scope.model.source }); - toastr.success('Data has been successfully imported into your vault.', 'Import Success'); - }); - }, importError); - } - - function cipherIsBadData(cipher) { - return (cipher.name === null || cipher.name === '--') && - (cipher.login && (cipher.login.password === null || cipher.login.password === '')); - } - - function importError(error) { - $analytics.eventTrack('Import Org Data Failed', { label: $scope.model.source }); - $uibModalInstance.dismiss('cancel'); - - if (error) { - var data = error.data; - if (data && data.ValidationErrors) { - var message = ''; - for (var key in data.ValidationErrors) { - if (!data.ValidationErrors.hasOwnProperty(key)) { - continue; - } - - for (var i = 0; i < data.ValidationErrors[key].length; i++) { - message += (key + ': ' + data.ValidationErrors[key][i] + ' '); - } - } - - if (message !== '') { - toastr.error(message); - return; - } - } - else if (data && data.Message) { - toastr.error(data.Message); - return; - } - else { - toastr.error(error); - return; - } - } - - toastr.error('Something went wrong. Try again.', 'Oh No!'); - } - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationVaultAddCipherController.js b/src/app/organization/organizationVaultAddCipherController.js deleted file mode 100644 index d7c659a9f3..0000000000 --- a/src/app/organization/organizationVaultAddCipherController.js +++ /dev/null @@ -1,141 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationVaultAddCipherController', function ($scope, apiService, $uibModalInstance, cryptoService, - cipherService, passwordService, $analytics, authService, orgId, $uibModal, constants, selectedType) { - $analytics.eventTrack('organizationVaultAddCipherController', { category: 'Modal' }); - $scope.constants = constants; - $scope.selectedType = selectedType ? selectedType.toString() : constants.cipherType.login.toString(); - $scope.cipher = { - type: selectedType || constants.cipherType.login, - login: { - uris: [{ - uri: null, - match: null, - matchValue: null - }] - }, - identity: {}, - card: {}, - secureNote: { - type: '0' - } - }; - $scope.hideFolders = $scope.hideFavorite = $scope.fromOrg = true; - - authService.getUserProfile().then(function (userProfile) { - var orgProfile = userProfile.organizations[orgId]; - $scope.useTotp = orgProfile.useTotp; - }); - - $scope.typeChanged = function () { - $scope.cipher.type = parseInt($scope.selectedType); - }; - - $scope.savePromise = null; - $scope.save = function () { - $scope.cipher.organizationId = orgId; - var cipher = cipherService.encryptCipher($scope.cipher); - $scope.savePromise = apiService.ciphers.postAdmin(cipher, function (cipherResponse) { - $analytics.eventTrack('Created Organization Cipher'); - var decCipher = cipherService.decryptCipherPreview(cipherResponse); - $uibModalInstance.close(decCipher); - }).$promise; - }; - - $scope.generatePassword = function () { - if (!$scope.cipher.login.password || confirm('Are you sure you want to overwrite the current password?')) { - $analytics.eventTrack('Generated Password From Add'); - $scope.cipher.login.password = passwordService.generatePassword({ length: 14, special: true }); - } - }; - - $scope.addUri = function () { - if (!$scope.cipher.login) { - return; - } - - if (!$scope.cipher.login.uris) { - $scope.cipher.login.uris = []; - } - - $scope.cipher.login.uris.push({ - uri: null, - match: null, - matchValue: null - }); - }; - - $scope.removeUri = function (uri) { - if (!$scope.cipher.login || !$scope.cipher.login.uris) { - return; - } - - var index = $scope.cipher.login.uris.indexOf(uri); - if (index > -1) { - $scope.cipher.login.uris.splice(index, 1); - } - }; - - $scope.uriMatchChanged = function (uri) { - if ((!uri.matchValue && uri.matchValue !== 0) || uri.matchValue === '') { - uri.match = null; - } - else { - uri.match = parseInt(uri.matchValue); - } - }; - - $scope.addField = function () { - if (!$scope.cipher.fields) { - $scope.cipher.fields = []; - } - - $scope.cipher.fields.push({ - type: constants.fieldType.text.toString(), - name: null, - value: null - }); - }; - - $scope.removeField = function (field) { - var index = $scope.cipher.fields.indexOf(field); - if (index > -1) { - $scope.cipher.fields.splice(index, 1); - } - }; - - $scope.clipboardSuccess = function (e) { - e.clearSelection(); - selectPassword(e); - }; - - $scope.clipboardError = function (e, password) { - if (password) { - selectPassword(e); - } - alert('Your web browser does not support easy clipboard copying. Copy it manually instead.'); - }; - - function selectPassword(e) { - var target = $(e.trigger).parent().prev(); - if (target.attr('type') === 'text') { - target.select(); - } - } - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - - $scope.showUpgrade = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/paidOrgRequired.html', - controller: 'paidOrgRequiredController', - resolve: { - orgId: function () { return orgId; } - } - }); - }; - }); diff --git a/src/app/organization/organizationVaultAttachmentsController.js b/src/app/organization/organizationVaultAttachmentsController.js deleted file mode 100644 index c87f2ca9f9..0000000000 --- a/src/app/organization/organizationVaultAttachmentsController.js +++ /dev/null @@ -1,90 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationVaultAttachmentsController', function ($scope, apiService, $uibModalInstance, cryptoService, - cipherService, cipherId, $analytics, validationService, toastr, $timeout) { - $analytics.eventTrack('organizationVaultAttachmentsController', { category: 'Modal' }); - $scope.cipher = {}; - $scope.loading = true; - $scope.isPremium = true; - $scope.canUseAttachments = true; - var closing = false; - - apiService.ciphers.getAdmin({ id: cipherId }, function (cipher) { - $scope.cipher = cipherService.decryptCipher(cipher); - $scope.loading = false; - }, function () { - $scope.loading = false; - }); - - $scope.save = function (form) { - var files = document.getElementById('file').files; - if (!files || !files.length) { - validationService.addError(form, 'file', 'Select a file.', true); - return; - } - - var key = cryptoService.getOrgKey($scope.cipher.organizationId); - $scope.savePromise = cipherService.encryptAttachmentFile(key, files[0]).then(function (encValue) { - var fd = new FormData(); - var blob = new Blob([encValue.data], { type: 'application/octet-stream' }); - fd.append('data', blob, encValue.fileName); - return apiService.ciphers.postAttachmentAdmin({ id: cipherId }, fd).$promise; - }).then(function (response) { - $analytics.eventTrack('Added Attachment'); - toastr.success('The attachment has been added.'); - closing = true; - $uibModalInstance.close(true); - }, function (e) { - var errors = validationService.parseErrors(e); - toastr.error(errors.length ? errors[0] : 'An error occurred.'); - }); - }; - - $scope.download = function (attachment) { - attachment.loading = true; - var key = cryptoService.getOrgKey($scope.cipher.organizationId); - cipherService.downloadAndDecryptAttachment(key, attachment, true).then(function (res) { - $timeout(function () { - attachment.loading = false; - }); - }, function () { - $timeout(function () { - attachment.loading = false; - }); - }); - }; - - $scope.remove = function (attachment) { - if (!confirm('Are you sure you want to delete this attachment (' + attachment.fileName + ')?')) { - return; - } - - attachment.loading = true; - apiService.ciphers.delAttachmentAdmin({ id: cipherId, attachmentId: attachment.id }).$promise.then(function () { - attachment.loading = false; - $analytics.eventTrack('Deleted Organization Attachment'); - var index = $scope.cipher.attachments.indexOf(attachment); - if (index > -1) { - $scope.cipher.attachments.splice(index, 1); - } - }, function () { - toastr.error('Cannot delete attachment.'); - attachment.loading = false; - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - $scope.$on('modal.closing', function (e, reason, closed) { - if (closing) { - return; - } - - e.preventDefault(); - closing = true; - $uibModalInstance.close(!!$scope.cipher.attachments && $scope.cipher.attachments.length > 0); - }); - }); diff --git a/src/app/organization/organizationVaultCipherCollectionsController.js b/src/app/organization/organizationVaultCipherCollectionsController.js deleted file mode 100644 index 1537da537f..0000000000 --- a/src/app/organization/organizationVaultCipherCollectionsController.js +++ /dev/null @@ -1,83 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationVaultCipherCollectionsController', function ($scope, apiService, $uibModalInstance, cipherService, - cipher, $analytics, collections) { - $analytics.eventTrack('organizationVaultCipherCollectionsController', { category: 'Modal' }); - $scope.cipher = {}; - $scope.collections = []; - $scope.selectedCollections = {}; - - $uibModalInstance.opened.then(function () { - var collectionUsed = []; - for (var i = 0; i < collections.length; i++) { - if (collections[i].id) { - collectionUsed.push(collections[i]); - } - } - $scope.collections = collectionUsed; - - $scope.cipher = cipher; - - var selectedCollections = {}; - if ($scope.cipher.collectionIds) { - for (i = 0; i < $scope.cipher.collectionIds.length; i++) { - selectedCollections[$scope.cipher.collectionIds[i]] = true; - } - } - $scope.selectedCollections = selectedCollections; - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - collections[$scope.collections[i].id] = true; - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = true; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedCollections).length === $scope.collections.length; - }; - - $scope.submit = function () { - var request = { - collectionIds: [] - }; - - for (var id in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(id)) { - request.collectionIds.push(id); - } - } - - $scope.submitPromise = apiService.ciphers.putCollectionsAdmin({ id: cipher.id }, request) - .$promise.then(function (response) { - $analytics.eventTrack('Edited Cipher Collections'); - $uibModalInstance.close({ - action: 'collectionsEdit', - collectionIds: request.collectionIds - }); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationVaultCipherEventsController.js b/src/app/organization/organizationVaultCipherEventsController.js deleted file mode 100644 index ad642ef7f6..0000000000 --- a/src/app/organization/organizationVaultCipherEventsController.js +++ /dev/null @@ -1,104 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationVaultCipherEventsController', function ($scope, apiService, $uibModalInstance, - cipher, $analytics, eventService) { - $analytics.eventTrack('organizationVaultCipherEventsController', { category: 'Modal' }); - $scope.cipher = cipher; - $scope.events = []; - $scope.loading = true; - $scope.continuationToken = null; - - var defaultFilters = eventService.getDefaultDateFilters(); - $scope.filterStart = defaultFilters.start; - $scope.filterEnd = defaultFilters.end; - - $uibModalInstance.opened.then(function () { - load(); - }); - - $scope.refresh = function () { - loadEvents(true); - }; - - $scope.next = function () { - loadEvents(false); - }; - - var i = 0, - orgUsersUserIdDict = {}, - orgUsersIdDict = {}; - - function load() { - apiService.organizationUsers.list({ orgId: cipher.organizationId }).$promise.then(function (list) { - var users = []; - for (i = 0; i < list.Data.length; i++) { - var user = { - id: list.Data[i].Id, - userId: list.Data[i].UserId, - name: list.Data[i].Name, - email: list.Data[i].Email - }; - - users.push(user); - - var displayName = user.name || user.email; - orgUsersUserIdDict[user.userId] = displayName; - orgUsersIdDict[user.id] = displayName; - } - - $scope.orgUsers = users; - - return loadEvents(true); - }); - } - - function loadEvents(clearExisting) { - var filterResult = eventService.formatDateFilters($scope.filterStart, $scope.filterEnd); - if (filterResult.error) { - alert(filterResult.error); - return; - } - - if (clearExisting) { - $scope.continuationToken = null; - $scope.events = []; - } - - $scope.loading = true; - return apiService.events.listCipher({ - id: cipher.id, - start: filterResult.start, - end: filterResult.end, - continuationToken: $scope.continuationToken - }).$promise.then(function (list) { - $scope.continuationToken = list.ContinuationToken; - - var events = []; - for (i = 0; i < list.Data.length; i++) { - var userId = list.Data[i].ActingUserId || list.Data[i].UserId; - var eventInfo = eventService.getEventInfo(list.Data[i], { cipherInfo: false }); - events.push({ - message: eventInfo.message, - appIcon: eventInfo.appIcon, - appName: eventInfo.appName, - userId: userId, - userName: userId ? (orgUsersUserIdDict[userId] || '-') : '-', - date: list.Data[i].Date, - ip: list.Data[i].IpAddress - }); - } - if ($scope.events && $scope.events.length > 0) { - $scope.events = $scope.events.concat(events); - } - else { - $scope.events = events; - } - $scope.loading = false; - }); - } - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/organization/organizationVaultController.js b/src/app/organization/organizationVaultController.js deleted file mode 100644 index 4ac7b82f90..0000000000 --- a/src/app/organization/organizationVaultController.js +++ /dev/null @@ -1,280 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationVaultController', function ($scope, apiService, cipherService, $analytics, $q, $state, - $localStorage, $uibModal, $filter, authService, $uibModalStack, constants, $timeout) { - $scope.ciphers = []; - $scope.collections = []; - $scope.loading = true; - $scope.useEvents = false; - $scope.constants = constants; - $scope.filter = undefined; - $scope.selectedType = undefined; - $scope.selectedCollection = undefined; - $scope.selectedAll = true; - $scope.selectedTitle = 'All'; - $scope.selectedIcon = 'fa-th'; - - $scope.$on('$viewContentLoaded', function () { - authService.getUserProfile().then(function (profile) { - if (profile.organizations) { - var org = profile.organizations[$state.params.orgId]; - $scope.useEvents = !!org.useEvents; - } - }); - - var collectionPromise = apiService.collections.listOrganization({ orgId: $state.params.orgId }, function (collections) { - var decCollections = [{ - id: null, - name: 'Unassigned' - }]; - - for (var i = 0; i < collections.Data.length; i++) { - var decCollection = cipherService.decryptCollection(collections.Data[i], null, true); - decCollections.push(decCollection); - } - - $scope.collections = decCollections; - }).$promise; - - var cipherPromise = apiService.ciphers.listOrganizationDetails({ organizationId: $state.params.orgId }, - function (ciphers) { - var decCiphers = []; - - for (var i = 0; i < ciphers.Data.length; i++) { - var decCipher = cipherService.decryptCipherPreview(ciphers.Data[i]); - decCiphers.push(decCipher); - } - - $scope.ciphers = decCiphers; - }).$promise; - - $q.all([collectionPromise, cipherPromise]).then(function () { - $scope.loading = false; - $timeout(function () { - if ($('body').hasClass('control-sidebar-open')) { - $("#search").focus(); - } - }, 500); - - if ($state.params.search) { - $uibModalStack.dismissAll(); - $scope.searchVaultText = $state.params.search; - } - - if ($state.params.viewEvents) { - $uibModalStack.dismissAll(); - var cipher = $filter('filter')($scope.ciphers, { id: $state.params.viewEvents }); - if (cipher && cipher.length) { - $scope.viewEvents(cipher[0]); - } - } - }); - }); - - $scope.collectionSort = function (item) { - if (!item.id) { - return ''; - } - - return item.name.toLowerCase(); - }; - - $scope.editCipher = function (cipher) { - var editModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultEditCipher.html', - controller: 'organizationVaultEditCipherController', - resolve: { - cipherId: function () { return cipher.id; }, - orgId: function () { return $state.params.orgId; } - } - }); - - editModel.result.then(function (returnVal) { - var index; - if (returnVal.action === 'edit') { - index = $scope.ciphers.indexOf(cipher); - if (index > -1) { - returnVal.data.collectionIds = $scope.ciphers[index].collectionIds; - $scope.ciphers[index] = returnVal.data; - } - } - else if (returnVal.action === 'delete') { - index = $scope.ciphers.indexOf(cipher); - if (index > -1) { - $scope.ciphers.splice(index, 1); - } - } - }); - }; - - $scope.$on('organizationVaultAddCipher', function (event, args) { - $scope.addCipher(); - }); - - $scope.addCipher = function () { - var addModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultAddCipher.html', - controller: 'organizationVaultAddCipherController', - resolve: { - orgId: function () { return $state.params.orgId; }, - selectedType: function () { return $scope.selectedType; } - } - }); - - addModel.result.then(function (addedCipher) { - $scope.ciphers.push(addedCipher); - }); - }; - - $scope.editCollections = function (cipher) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationVaultCipherCollections.html', - controller: 'organizationVaultCipherCollectionsController', - resolve: { - cipher: function () { return cipher; }, - collections: function () { return $scope.collections; } - } - }); - - modal.result.then(function (response) { - if (response.collectionIds) { - cipher.collectionIds = response.collectionIds; - } - }); - }; - - $scope.viewEvents = function (cipher) { - $uibModal.open({ - animation: true, - templateUrl: 'app/organization/views/organizationVaultCipherEvents.html', - controller: 'organizationVaultCipherEventsController', - resolve: { - cipher: function () { return cipher; } - } - }); - }; - - $scope.attachments = function (cipher) { - authService.getUserProfile().then(function (profile) { - return !!profile.organizations[cipher.organizationId].maxStorageGb; - }).then(function (useStorage) { - if (!useStorage) { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/paidOrgRequired.html', - controller: 'paidOrgRequiredController', - resolve: { - orgId: function () { return cipher.organizationId; } - } - }); - return; - } - - var attachmentModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultAttachments.html', - controller: 'organizationVaultAttachmentsController', - resolve: { - cipherId: function () { return cipher.id; } - } - }); - - attachmentModel.result.then(function (hasAttachments) { - cipher.hasAttachments = hasAttachments; - }); - }); - }; - - $scope.deleteCipher = function (cipher) { - if (!confirm('Are you sure you want to delete this item (' + cipher.name + ')?')) { - return; - } - - apiService.ciphers.delAdmin({ id: cipher.id }, function () { - $analytics.eventTrack('Deleted Cipher'); - var index = $scope.ciphers.indexOf(cipher); - if (index > -1) { - $scope.ciphers.splice(index, 1); - } - }); - }; - - $scope.filterCollection = function (col) { - resetSelected(); - $scope.selectedCollection = col; - $scope.selectedIcon = 'fa-cube'; - if (col.id) { - $scope.filter = function (c) { - return c.collectionIds && c.collectionIds.indexOf(col.id) > -1; - }; - } - else { - $scope.filter = function (c) { - return !c.collectionIds || c.collectionIds.length === 0; - }; - } - fixLayout(); - }; - - $scope.filterType = function (t) { - resetSelected(); - $scope.selectedType = t; - switch (t) { - case constants.cipherType.login: - $scope.selectedTitle = 'Login'; - $scope.selectedIcon = 'fa-globe'; - break; - case constants.cipherType.card: - $scope.selectedTitle = 'Card'; - $scope.selectedIcon = 'fa-credit-card'; - break; - case constants.cipherType.identity: - $scope.selectedTitle = 'Identity'; - $scope.selectedIcon = 'fa-id-card-o'; - break; - case constants.cipherType.secureNote: - $scope.selectedTitle = 'Secure Note'; - $scope.selectedIcon = 'fa-sticky-note-o'; - break; - default: - break; - } - $scope.filter = function (c) { - return c.type === t; - }; - fixLayout(); - }; - - $scope.filterAll = function () { - resetSelected(); - $scope.selectedAll = true; - $scope.selectedTitle = 'All'; - $scope.selectedIcon = 'fa-th'; - $scope.filter = null; - fixLayout(); - }; - - function resetSelected() { - $scope.selectedCollection = undefined; - $scope.selectedType = undefined; - $scope.selectedAll = false; - } - - function fixLayout() { - if ($.AdminLTE && $.AdminLTE.layout) { - $timeout(function () { - $.AdminLTE.layout.fix(); - }, 0); - } - } - - $scope.cipherFilter = function () { - return function (cipher) { - return !$scope.filter || $scope.filter(cipher); - }; - }; - }); diff --git a/src/app/organization/organizationVaultEditCipherController.js b/src/app/organization/organizationVaultEditCipherController.js deleted file mode 100644 index 87bf870a7f..0000000000 --- a/src/app/organization/organizationVaultEditCipherController.js +++ /dev/null @@ -1,148 +0,0 @@ -angular - .module('bit.organization') - - .controller('organizationVaultEditCipherController', function ($scope, apiService, $uibModalInstance, cryptoService, - cipherService, passwordService, cipherId, $analytics, orgId, $uibModal, constants) { - $analytics.eventTrack('organizationVaultEditCipherController', { category: 'Modal' }); - $scope.cipher = {}; - $scope.hideFolders = $scope.hideFavorite = $scope.fromOrg = true; - $scope.constants = constants; - - apiService.ciphers.getAdmin({ id: cipherId }, function (cipher) { - $scope.cipher = cipherService.decryptCipher(cipher); - $scope.useTotp = $scope.cipher.organizationUseTotp; - setUriMatchValues(); - }); - - $scope.save = function (model) { - var cipher = cipherService.encryptCipher(model, $scope.cipher.type); - $scope.savePromise = apiService.ciphers.putAdmin({ id: cipherId }, cipher, function (cipherResponse) { - $analytics.eventTrack('Edited Organization Cipher'); - var decCipher = cipherService.decryptCipherPreview(cipherResponse); - $uibModalInstance.close({ - action: 'edit', - data: decCipher - }); - }).$promise; - }; - - $scope.generatePassword = function () { - if (!$scope.cipher.login.password || confirm('Are you sure you want to overwrite the current password?')) { - $analytics.eventTrack('Generated Password From Edit'); - $scope.cipher.login.password = passwordService.generatePassword({ length: 14, special: true }); - } - }; - - $scope.addUri = function () { - if (!$scope.cipher.login) { - return; - } - - if (!$scope.cipher.login.uris) { - $scope.cipher.login.uris = []; - } - - $scope.cipher.login.uris.push({ - uri: null, - match: null, - matchValue: null - }); - }; - - $scope.removeUri = function (uri) { - if (!$scope.cipher.login || !$scope.cipher.login.uris) { - return; - } - - var index = $scope.cipher.login.uris.indexOf(uri); - if (index > -1) { - $scope.cipher.login.uris.splice(index, 1); - } - }; - - $scope.uriMatchChanged = function (uri) { - if ((!uri.matchValue && uri.matchValue !== 0) || uri.matchValue === '') { - uri.match = null; - } - else { - uri.match = parseInt(uri.matchValue); - } - }; - - $scope.addField = function () { - if (!$scope.cipher.login.fields) { - $scope.cipher.login.fields = []; - } - - $scope.cipher.fields.push({ - type: constants.fieldType.text.toString(), - name: null, - value: null - }); - }; - - $scope.removeField = function (field) { - var index = $scope.cipher.fields.indexOf(field); - if (index > -1) { - $scope.cipher.fields.splice(index, 1); - } - }; - - $scope.clipboardSuccess = function (e) { - e.clearSelection(); - selectPassword(e); - }; - - $scope.clipboardError = function (e, password) { - if (password) { - selectPassword(e); - } - alert('Your web browser does not support easy clipboard copying. Copy it manually instead.'); - }; - - function selectPassword(e) { - var target = $(e.trigger).parent().prev(); - if (target.attr('type') === 'text') { - target.select(); - } - } - - $scope.delete = function () { - if (!confirm('Are you sure you want to delete this item (' + $scope.cipher.name + ')?')) { - return; - } - - apiService.ciphers.delAdmin({ id: $scope.cipher.id }, function () { - $analytics.eventTrack('Deleted Organization Cipher From Edit'); - $uibModalInstance.close({ - action: 'delete', - data: $scope.cipher.id - }); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - $scope.showUpgrade = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/paidOrgRequired.html', - controller: 'paidOrgRequiredController', - resolve: { - orgId: function () { return orgId; } - } - }); - }; - - function setUriMatchValues() { - if ($scope.cipher.login && $scope.cipher.login.uris) { - for (var i = 0; i < $scope.cipher.login.uris.length; i++) { - $scope.cipher.login.uris[i].matchValue = - $scope.cipher.login.uris[i].match || $scope.cipher.login.uris[i].match === 0 ? - $scope.cipher.login.uris[i].match.toString() : ''; - } - } - } - }); diff --git a/src/app/organization/views/organizationBilling.html b/src/app/organization/views/organizationBilling.html deleted file mode 100644 index b80b84564d..0000000000 --- a/src/app/organization/views/organizationBilling.html +++ /dev/null @@ -1,230 +0,0 @@ -
-

- Billing - manage your billing & licensing -

-
-
-
-

Canceled

- The subscription to this organization has been canceled. -
-
-

Pending Cancellation

-

- The subscription to this organization has been marked for cancellation at the end of the - current billing period. -

- -
-
-
-

Plan

-
-
-
-
-
-
Name
-
{{plan.name || '-'}}
-
Expiration
-
- Loading... -
-
- {{expiration | date: 'medium'}} -
-
- Never expires -
-
-
-
Name
-
{{plan.name || '-'}}
-
Total Seats
-
{{plan.seats || '-'}}
-
-
-
-
-
Status
-
- {{(subscription && subscription.status) || '-'}} - - marked for cancellation -
-
Next Charge
-
{{nextInvoice ? ((nextInvoice.date | date: 'mediumDate') + ', ' + (nextInvoice.amount | currency:'$')) : '-'}}
-
-
-
-
-
- Details -
- Loading... -
-
- - - - - - - -
- {{item.name}} {{item.qty > 1 ? '×' + item.qty : ''}} - @ {{item.amount | currency:'$'}} /{{item.interval}} - {{(item.qty * item.amount) | currency:'$'}} /{{item.interval}}
-
-
-
-
- - -
-
-
-

User Seats

-
-
-
- Loading... -
-
- Your plan currently has a total of {{plan.seats}} seats. -
-
- -
-
-
-

Storage

-
-
-

- Your plan has a total of {{storage.maxGb}} GB of encrypted file storage. - You are currently using {{storage.currentName}}. -

-
-
- {{storage.percentage}}% -
-
-
- -
-
-
-

Payment Method

-
-
-
- Loading... -
-
- No payment method on file. -
-
-
-

You must verify your bank account

-

- We have made two micro-deposits to your bank account (it may take 1-2 business days to show up). - Enter these amounts to verify the bank account. Failure to verify the bank account will result in a - missed payment and your organization being disabled. -

- -
- - {{paymentSource.description}} -
-
- -
-
-
-

Charges

-
-
-
- Loading... -
-
- No charges. -
-
- - - - - - - - - - -
- - - - - {{charge.date | date: 'mediumDate'}} - - {{charge.paymentSource}} - - {{charge.status}} - - {{charge.amount | currency:'$'}} -
-
-
- -
-
diff --git a/src/app/organization/views/organizationBillingAdjustSeats.html b/src/app/organization/views/organizationBillingAdjustSeats.html deleted file mode 100644 index 7352e41702..0000000000 --- a/src/app/organization/views/organizationBillingAdjustSeats.html +++ /dev/null @@ -1,46 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationBillingChangePlan.html b/src/app/organization/views/organizationBillingChangePlan.html deleted file mode 100644 index c6e18b5ff6..0000000000 --- a/src/app/organization/views/organizationBillingChangePlan.html +++ /dev/null @@ -1,14 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationBillingVerifyBank.html b/src/app/organization/views/organizationBillingVerifyBank.html deleted file mode 100644 index 6a17d33a38..0000000000 --- a/src/app/organization/views/organizationBillingVerifyBank.html +++ /dev/null @@ -1,43 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationCollections.html b/src/app/organization/views/organizationCollections.html deleted file mode 100644 index 971c5f96b0..0000000000 --- a/src/app/organization/views/organizationCollections.html +++ /dev/null @@ -1,70 +0,0 @@ -
-

- Collections - control what you share -

-
-
-
-
-   - -
- -
-
-
-
- Loading... -
-
- No collections to list. -
-
-

There are no collections yet for your organization.

- -
-
- - - - - - - -
-
- - -
-
- - {{collection.name}} - -
-
-
-
-
diff --git a/src/app/organization/views/organizationCollectionsAdd.html b/src/app/organization/views/organizationCollectionsAdd.html deleted file mode 100644 index f54dc06301..0000000000 --- a/src/app/organization/views/organizationCollectionsAdd.html +++ /dev/null @@ -1,83 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationCollectionsEdit.html b/src/app/organization/views/organizationCollectionsEdit.html deleted file mode 100644 index 5b8a5a4e73..0000000000 --- a/src/app/organization/views/organizationCollectionsEdit.html +++ /dev/null @@ -1,84 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationCollectionsUsers.html b/src/app/organization/views/organizationCollectionsUsers.html deleted file mode 100644 index 65ead9aed7..0000000000 --- a/src/app/organization/views/organizationCollectionsUsers.html +++ /dev/null @@ -1,64 +0,0 @@ - - - diff --git a/src/app/organization/views/organizationDashboard.html b/src/app/organization/views/organizationDashboard.html deleted file mode 100644 index 82bc953b05..0000000000 --- a/src/app/organization/views/organizationDashboard.html +++ /dev/null @@ -1,34 +0,0 @@ -
-

- Dashboard - {{orgProfile.name}} -

-
-
-
-

Organization Disabled

-

This organization is currently disabled. Users will not see your shared logins or collections.

-

Contact us if you would like to reinstate this organization.

-

Update your license to reinstate this organization.

- - Billing & Licensing - - - Contact Us - -
-
-
-

Let's Get Started!

-
-
-

Get started by inviting users and creating your collections.

- - Invite Users - - - Manage Collections - -
-
-
diff --git a/src/app/organization/views/organizationDelete.html b/src/app/organization/views/organizationDelete.html deleted file mode 100644 index 5669adde32..0000000000 --- a/src/app/organization/views/organizationDelete.html +++ /dev/null @@ -1,34 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationEvents.html b/src/app/organization/views/organizationEvents.html deleted file mode 100644 index 0fe14988c3..0000000000 --- a/src/app/organization/views/organizationEvents.html +++ /dev/null @@ -1,67 +0,0 @@ -
-

- Events - audit your organization -

-
-
-
-
-   - -
- -
-
-
-
- Loading... -
-
-

There are no events to list.

-
-
- - - - - - - - - - - - - - - - - -
TimestampAppUserEvent
- {{event.date | date:'medium'}} - - - - {{event.userName}} - -
-
-
-
- -
-
diff --git a/src/app/organization/views/organizationGroups.html b/src/app/organization/views/organizationGroups.html deleted file mode 100644 index ca26a99827..0000000000 --- a/src/app/organization/views/organizationGroups.html +++ /dev/null @@ -1,70 +0,0 @@ -
-

- Groups - organize your users -

-
-
-
-
-   - -
- -
-
-
-
- Loading... -
-
- No groups to list. -
-
-

There are no groups yet for your organization.

- -
-
- - - - - - - -
-
- - -
-
- - {{group.name}} - -
-
-
-
-
diff --git a/src/app/organization/views/organizationGroupsAdd.html b/src/app/organization/views/organizationGroupsAdd.html deleted file mode 100644 index ed2d500222..0000000000 --- a/src/app/organization/views/organizationGroupsAdd.html +++ /dev/null @@ -1,95 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationGroupsEdit.html b/src/app/organization/views/organizationGroupsEdit.html deleted file mode 100644 index 615fdf0f10..0000000000 --- a/src/app/organization/views/organizationGroupsEdit.html +++ /dev/null @@ -1,95 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationGroupsUsers.html b/src/app/organization/views/organizationGroupsUsers.html deleted file mode 100644 index 219916fc1a..0000000000 --- a/src/app/organization/views/organizationGroupsUsers.html +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/src/app/organization/views/organizationPeople.html b/src/app/organization/views/organizationPeople.html deleted file mode 100644 index 4049a17919..0000000000 --- a/src/app/organization/views/organizationPeople.html +++ /dev/null @@ -1,96 +0,0 @@ -
-

- People - users for your organization -

-
-
-
-
-   - -
- -
-
-
-
- Loading... -
-
- - - - - - - - - - -
- - - - - {{user.email}} - -
{{user.name}}
-
- {{user.type | enumName: 'OrgUserType'}} - - - {{user.status | enumName: 'OrgUserStatus'}} - -
-
-
-
-
diff --git a/src/app/organization/views/organizationPeopleEdit.html b/src/app/organization/views/organizationPeopleEdit.html deleted file mode 100644 index 48f61d207b..0000000000 --- a/src/app/organization/views/organizationPeopleEdit.html +++ /dev/null @@ -1,101 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationPeopleEvents.html b/src/app/organization/views/organizationPeopleEvents.html deleted file mode 100644 index 2dcf521555..0000000000 --- a/src/app/organization/views/organizationPeopleEvents.html +++ /dev/null @@ -1,56 +0,0 @@ - - - diff --git a/src/app/organization/views/organizationPeopleGroups.html b/src/app/organization/views/organizationPeopleGroups.html deleted file mode 100644 index ba482a195c..0000000000 --- a/src/app/organization/views/organizationPeopleGroups.html +++ /dev/null @@ -1,55 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationPeopleInvite.html b/src/app/organization/views/organizationPeopleInvite.html deleted file mode 100644 index 5541d8d676..0000000000 --- a/src/app/organization/views/organizationPeopleInvite.html +++ /dev/null @@ -1,110 +0,0 @@ - -
- - -
diff --git a/src/app/organization/views/organizationSettings.html b/src/app/organization/views/organizationSettings.html deleted file mode 100644 index 55cf237982..0000000000 --- a/src/app/organization/views/organizationSettings.html +++ /dev/null @@ -1,124 +0,0 @@ -
-

- Settings - manage your organization -

-
-
-
-
-

General

-
-
-
-
-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- - -
-
- - -
-
- - -
-
-
- Tax Information -
{{model.businessAddress1}}
-
{{model.businessAddress2}}
-
{{model.businessAddress3}}
-
{{model.businessCountry}}
-
{{model.businessTaxNumber}}
-

- Please contact support - to provide (or update) tax information for your invoices. -

-
-
-
- -
-
-
- -
-
-
-
-

Two-step Login Providers

-
-
-
- - - - - - - - -
- - {{::provider.name}} - - - {{::provider.name}} -
{{::provider.description}}
-
- - {{provider.enabled ? 'Enabled' : 'Disabled'}} - -
-
-
-
-
-
-

Import/Export

-
-
-

- Quickly import logins, collections, and other data. You can also export all of your organization's - vault data in .csv format. -

-
- -
-
-
-

Danger Zone

-
-
- Careful, these actions are not reversible! -
- -
-
diff --git a/src/app/organization/views/organizationVault.html b/src/app/organization/views/organizationVault.html deleted file mode 100644 index b41ab1d84f..0000000000 --- a/src/app/organization/views/organizationVault.html +++ /dev/null @@ -1,142 +0,0 @@ -
-

- Org Vault - - , - - -

-
-
-

Loading...

-
-
-

- - {{selectedCollection ? selectedCollection.name : selectedTitle}} - -

-
-
-
No items to list.
-
- - - - - - - - -
- - - - - - {{cipher.name}} - -
{{cipher.subTitle}}
-
-
-
-
-
- diff --git a/src/app/organization/views/organizationVaultCipherCollections.html b/src/app/organization/views/organizationVaultCipherCollections.html deleted file mode 100644 index 19d9a56b37..0000000000 --- a/src/app/organization/views/organizationVaultCipherCollections.html +++ /dev/null @@ -1,52 +0,0 @@ - -
- - -
\ No newline at end of file diff --git a/src/app/organization/views/organizationVaultCipherEvents.html b/src/app/organization/views/organizationVaultCipherEvents.html deleted file mode 100644 index 8a7e9307a0..0000000000 --- a/src/app/organization/views/organizationVaultCipherEvents.html +++ /dev/null @@ -1,60 +0,0 @@ - - - diff --git a/src/app/organizations/manage/collections.component.html b/src/app/organizations/manage/collections.component.html new file mode 100644 index 0000000000..8bc219c243 --- /dev/null +++ b/src/app/organizations/manage/collections.component.html @@ -0,0 +1,43 @@ + + + +

{{'noItemsInList' | i18n}}

+ + + + + + + +
+ {{c.name}} + + +
+
diff --git a/src/app/organizations/manage/collections.component.ts b/src/app/organizations/manage/collections.component.ts new file mode 100644 index 0000000000..782f192a47 --- /dev/null +++ b/src/app/organizations/manage/collections.component.ts @@ -0,0 +1,42 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; + +import { CollectionData } from 'jslib/models/data/collectionData'; +import { Collection } from 'jslib/models/domain/collection'; +import { CollectionDetailsResponse } from 'jslib/models/response/collectionResponse'; +import { CollectionView } from 'jslib/models/view/collectionView'; + +@Component({ + selector: 'app-org-manage-collections', + templateUrl: 'collections.component.html', +}) +export class CollectionsComponent implements OnInit { + loading = true; + organizationId: string; + collections: CollectionView[]; + searchText: string; + + constructor(private apiService: ApiService, private route: ActivatedRoute, + private collectionService: CollectionService) { } + + async ngOnInit() { + this.route.parent.parent.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + await this.load(); + }); + } + + async load() { + const response = await this.apiService.getCollections(this.organizationId); + const collections = response.data.map((r) => + new Collection(new CollectionData(r as CollectionDetailsResponse))); + this.collections = await this.collectionService.decryptMany(collections); + this.loading = false; + } +} diff --git a/src/app/organizations/manage/events.component.html b/src/app/organizations/manage/events.component.html new file mode 100644 index 0000000000..a9ea1ded78 --- /dev/null +++ b/src/app/organizations/manage/events.component.html @@ -0,0 +1,50 @@ + + + +

{{'noItemsInList' | i18n}}

+ + + + + + + + + + + + + + + + + +
{{'timestamp' | i18n}} + {{'device' | i18n}} + {{'user' | i18n}}{{'event' | i18n}}
{{e.date | date:'medium'}} + + + {{e.userName}} +
+ +
diff --git a/src/app/organizations/manage/events.component.ts b/src/app/organizations/manage/events.component.ts new file mode 100644 index 0000000000..9591bdb255 --- /dev/null +++ b/src/app/organizations/manage/events.component.ts @@ -0,0 +1,115 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { EventService } from '../../services/event.service'; + +import { EventResponse } from 'jslib/models/response/eventResponse'; +import { ListResponse } from 'jslib/models/response/listResponse'; + +@Component({ + selector: 'app-org-events', + templateUrl: 'events.component.html', +}) +export class EventsComponent implements OnInit { + loading = true; + loaded = false; + organizationId: string; + events: any[]; + start: string; + end: string; + continuationToken: string; + refreshPromise: Promise; + morePromise: Promise; + + private orgUsersUserIdMap = new Map(); + private orgUsersIdMap = new Map(); + + constructor(private apiService: ApiService, private route: ActivatedRoute, + private eventService: EventService, private i18nService: I18nService, + private toasterService: ToasterService) { } + + async ngOnInit() { + this.route.parent.parent.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + const defaultDates = this.eventService.getDefaultDateFilters(); + this.start = defaultDates[0]; + this.end = defaultDates[1]; + await this.load(); + }); + } + + async load() { + const response = await this.apiService.getOrganizationUsers(this.organizationId); + response.data.forEach((u) => { + const name = u.name == null || u.name.trim() === '' ? u.email : u.name; + this.orgUsersIdMap.set(u.id, { name: name, email: u.email }); + this.orgUsersUserIdMap.set(u.userId, { name: name, email: u.email }); + }); + await this.loadEvents(true); + this.loaded = true; + } + + async loadEvents(clearExisting: boolean) { + if (this.refreshPromise != null || this.morePromise != null) { + return; + } + + let dates: string[] = null; + try { + dates = this.eventService.formatDateFilters(this.start, this.end); + } catch (e) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('invalidDateRange')); + return; + } + + this.loading = true; + let response: ListResponse; + try { + const promise = this.apiService.getEventsOrganization(this.organizationId, dates[0], dates[1], + clearExisting ? null : this.continuationToken); + if (clearExisting) { + this.refreshPromise = promise; + } else { + this.morePromise = promise; + } + response = await promise; + } catch { } + + this.continuationToken = response.continuationToken; + const events = response.data.map((r) => { + const userId = r.actingUserId == null ? r.userId : r.actingUserId; + const eventInfo = this.eventService.getEventInfo(r); + const user = userId != null && this.orgUsersUserIdMap.has(userId) ? + this.orgUsersUserIdMap.get(userId) : null; + return { + message: eventInfo.message, + appIcon: eventInfo.appIcon, + appName: eventInfo.appName, + userId: userId, + userName: user != null ? user.name : this.i18nService.t('unknown'), + userEmail: user != null ? user.email : '', + date: r.date, + ip: r.ipAddress, + }; + }); + + if (!clearExisting && this.events != null && this.events.length > 0) { + this.events = this.events.concat(events); + } else { + this.events = events; + } + + this.loading = false; + this.morePromise = null; + this.refreshPromise = null; + } +} diff --git a/src/app/organizations/manage/group-add-edit.component.html b/src/app/organizations/manage/group-add-edit.component.html new file mode 100644 index 0000000000..b613947b48 --- /dev/null +++ b/src/app/organizations/manage/group-add-edit.component.html @@ -0,0 +1,90 @@ + diff --git a/src/app/organizations/manage/group-add-edit.component.ts b/src/app/organizations/manage/group-add-edit.component.ts new file mode 100644 index 0000000000..809c5efc96 --- /dev/null +++ b/src/app/organizations/manage/group-add-edit.component.ts @@ -0,0 +1,141 @@ +import { + Component, + EventEmitter, + Input, + OnInit, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { CollectionData } from 'jslib/models/data/collectionData'; +import { Collection } from 'jslib/models/domain/collection'; +import { GroupRequest } from 'jslib/models/request/groupRequest'; +import { SelectionReadOnlyRequest } from 'jslib/models/request/selectionReadOnlyRequest'; +import { CollectionDetailsResponse } from 'jslib/models/response/collectionResponse'; +import { CollectionView } from 'jslib/models/view/collectionView'; + +@Component({ + selector: 'app-group-add-edit', + templateUrl: 'group-add-edit.component.html', +}) +export class GroupAddEditComponent implements OnInit { + @Input() groupId: string; + @Input() organizationId: string; + @Output() onSavedGroup = new EventEmitter(); + @Output() onDeletedGroup = new EventEmitter(); + + loading = true; + editMode: boolean = false; + title: string; + name: string; + externalId: string; + access: 'all' | 'selected' = 'all'; + collections: CollectionView[] = []; + formPromise: Promise; + deletePromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private collectionService: CollectionService, private platformUtilsService: PlatformUtilsService) { } + + async ngOnInit() { + this.editMode = this.loading = this.groupId != null; + await this.loadCollections(); + + if (this.editMode) { + this.editMode = true; + this.title = this.i18nService.t('editGroup'); + try { + const group = await this.apiService.getGroupDetails(this.organizationId, this.groupId); + this.access = group.accessAll ? 'all' : 'selected'; + this.name = group.name; + this.externalId = group.externalId; + if (group.collections != null && this.collections != null) { + group.collections.forEach((s) => { + const collection = this.collections.filter((c) => c.id === s.id); + if (collection != null && collection.length > 0) { + (collection[0] as any).checked = true; + collection[0].readOnly = s.readOnly; + } + }); + } + } catch { } + } else { + this.title = this.i18nService.t('addGroup'); + } + + this.loading = false; + } + + async loadCollections() { + const response = await this.apiService.getCollections(this.organizationId); + const collections = response.data.map((r) => + new Collection(new CollectionData(r as CollectionDetailsResponse))); + this.collections = await this.collectionService.decryptMany(collections); + } + + check(c: CollectionView, select?: boolean) { + (c as any).checked = select == null ? !(c as any).checked : select; + if (!(c as any).checked) { + c.readOnly = false; + } + } + + selectAll(select: boolean) { + this.collections.forEach((c) => this.check(c, select)); + } + + async submit() { + const request = new GroupRequest(); + request.name = this.name; + request.externalId = this.externalId; + request.accessAll = this.access === 'all'; + if (!request.accessAll) { + request.collections = this.collections.filter((c) => (c as any).checked) + .map((c) => new SelectionReadOnlyRequest(c.id, !!c.readOnly)); + } + + try { + if (this.editMode) { + this.formPromise = this.apiService.putGroup(this.organizationId, this.groupId, request); + } else { + this.formPromise = this.apiService.postGroup(this.organizationId, request); + } + await this.formPromise; + this.analytics.eventTrack.next({ action: this.editMode ? 'Edited Group' : 'Created Group' }); + this.toasterService.popAsync('success', null, + this.i18nService.t(this.editMode ? 'editedThing' : 'createdThing', + this.i18nService.t('group').toLocaleLowerCase(), this.name)); + this.onSavedGroup.emit(); + } catch { } + } + + async delete() { + if (!this.editMode) { + return; + } + + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t('deleteGroupConfirmation'), this.name, + this.i18nService.t('yes'), this.i18nService.t('no'), 'warning'); + if (!confirmed) { + return false; + } + + try { + this.deletePromise = this.apiService.deleteGroup(this.organizationId, this.groupId); + await this.deletePromise; + this.analytics.eventTrack.next({ action: 'Deleted Group' }); + this.toasterService.popAsync('success', null, + this.i18nService.t('deletedThing', this.i18nService.t('group').toLocaleLowerCase(), this.name)); + this.onDeletedGroup.emit(); + } catch { } + } +} diff --git a/src/app/organizations/manage/groups.component.html b/src/app/organizations/manage/groups.component.html new file mode 100644 index 0000000000..c495b4d485 --- /dev/null +++ b/src/app/organizations/manage/groups.component.html @@ -0,0 +1,44 @@ + + + +

{{'noItemsInList' | i18n}}

+ + + + + + + +
+ {{g.name}} + + +
+
+ diff --git a/src/app/organizations/manage/groups.component.ts b/src/app/organizations/manage/groups.component.ts new file mode 100644 index 0000000000..3baf817085 --- /dev/null +++ b/src/app/organizations/manage/groups.component.ts @@ -0,0 +1,104 @@ +import { + Component, + ComponentFactoryResolver, + OnInit, + ViewChild, + ViewContainerRef, +} from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { GroupResponse } from 'jslib/models/response/groupResponse'; + +import { Utils } from 'jslib/misc/utils'; + +import { ModalComponent } from '../../modal.component'; +import { GroupAddEditComponent } from './group-add-edit.component'; + +@Component({ + selector: 'app-org-groups', + templateUrl: 'groups.component.html', +}) +export class GroupsComponent implements OnInit { + @ViewChild('addEdit', { read: ViewContainerRef }) addEditModalRef: ViewContainerRef; + + loading = true; + organizationId: string; + groups: GroupResponse[]; + searchText: string; + + private modal: ModalComponent = null; + + constructor(private apiService: ApiService, private route: ActivatedRoute, + private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver, + private analytics: Angulartics2, private toasterService: ToasterService, + private platformUtilsService: PlatformUtilsService) { } + + async ngOnInit() { + this.route.parent.parent.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + await this.load(); + }); + } + + async load() { + const response = await this.apiService.getGroups(this.organizationId); + const groups = response.data != null && response.data.length > 0 ? response.data : []; + groups.sort(Utils.getSortFunction(this.i18nService, 'name')); + this.groups = groups; + this.loading = false; + } + + edit(group: GroupResponse) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.addEditModalRef.createComponent(factory).instance; + const childComponent = this.modal.show( + GroupAddEditComponent, this.addEditModalRef); + + childComponent.organizationId = this.organizationId; + childComponent.groupId = group != null ? group.id : null; + childComponent.onSavedGroup.subscribe(() => { + this.modal.close(); + this.load(); + }); + childComponent.onDeletedGroup.subscribe(() => { + this.modal.close(); + this.load(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + add() { + this.edit(null); + } + + async delete(group: GroupResponse) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t('deleteGroupConfirmation'), group.name, + this.i18nService.t('yes'), this.i18nService.t('no'), 'warning'); + if (!confirmed) { + return false; + } + + try { + await this.apiService.deleteGroup(this.organizationId, group.id); + this.analytics.eventTrack.next({ action: 'Deleted Group' }); + this.toasterService.popAsync('success', null, + this.i18nService.t('deletedThing', this.i18nService.t('group').toLocaleLowerCase(), group.name)); + await this.load(); + } catch { } + } +} diff --git a/src/app/organizations/manage/manage.component.html b/src/app/organizations/manage/manage.component.html new file mode 100644 index 0000000000..786bff8ee7 --- /dev/null +++ b/src/app/organizations/manage/manage.component.html @@ -0,0 +1,26 @@ + diff --git a/src/app/organizations/manage/manage.component.ts b/src/app/organizations/manage/manage.component.ts new file mode 100644 index 0000000000..1d2f36c96d --- /dev/null +++ b/src/app/organizations/manage/manage.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-org-manage', + templateUrl: 'manage.component.html', +}) +export class ManageComponent { } diff --git a/src/app/organizations/manage/people.component.html b/src/app/organizations/manage/people.component.html new file mode 100644 index 0000000000..837f9ac415 --- /dev/null +++ b/src/app/organizations/manage/people.component.html @@ -0,0 +1,71 @@ + + + +

{{'noItemsInList' | i18n}}

+ + + + + + + + + +
+ + + {{u.email}} + {{'invited' | i18n}} + {{'accepted' | i18n}} + {{u.name}} + + {{'owner' | i18n}} + {{'admin' | i18n}} + {{'user' | i18n}} + + +
+
diff --git a/src/app/organizations/manage/people.component.ts b/src/app/organizations/manage/people.component.ts new file mode 100644 index 0000000000..43cf189aaa --- /dev/null +++ b/src/app/organizations/manage/people.component.ts @@ -0,0 +1,46 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { OrganizationUserUserDetailsResponse } from 'jslib/models/response/organizationUserResponse'; + +import { OrganizationUserStatusType } from 'jslib/enums/organizationUserStatusType'; +import { OrganizationUserType } from 'jslib/enums/organizationUserType'; + +import { Utils } from 'jslib/misc/utils'; + +@Component({ + selector: 'app-org-people', + templateUrl: 'people.component.html', +}) +export class PeopleComponent implements OnInit { + loading = true; + organizationId: string; + users: OrganizationUserUserDetailsResponse[]; + searchText: string; + organizationUserType = OrganizationUserType; + organizationUserStatusType = OrganizationUserStatusType; + + constructor(private apiService: ApiService, private route: ActivatedRoute, + private i18nService: I18nService) { } + + async ngOnInit() { + this.route.parent.parent.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + await this.load(); + }); + } + + async load() { + const response = await this.apiService.getOrganizationUsers(this.organizationId); + const users = response.data != null && response.data.length > 0 ? response.data : []; + users.sort(Utils.getSortFunction(this.i18nService, 'email')); + this.users = users; + this.loading = false; + } +} diff --git a/src/app/organizations/tools/export.component.ts b/src/app/organizations/tools/export.component.ts new file mode 100644 index 0000000000..454c067e29 --- /dev/null +++ b/src/app/organizations/tools/export.component.ts @@ -0,0 +1,43 @@ +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { Component } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { ExportService } from 'jslib/abstractions/export.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { ExportComponent as BaseExportComponent } from '../../tools/export.component'; + +@Component({ + selector: 'app-org-export', + templateUrl: '../../tools/export.component.html', +}) +export class ExportComponent extends BaseExportComponent { + organizationId: string; + + constructor(analytics: Angulartics2, toasterService: ToasterService, + cryptoService: CryptoService, userService: UserService, + i18nService: I18nService, platformUtilsService: PlatformUtilsService, + exportService: ExportService, private route: ActivatedRoute) { + super(analytics, toasterService, cryptoService, userService, i18nService, platformUtilsService, + exportService); + } + + ngOnInit() { + this.route.parent.parent.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + }); + } + + getExportData() { + return this.exportService.getOrganizationExport(this.organizationId, 'csv'); + } + + getFileName() { + return super.getFileName('org'); + } +} diff --git a/src/app/organizations/tools/import.component.ts b/src/app/organizations/tools/import.component.ts new file mode 100644 index 0000000000..24a44d35c6 --- /dev/null +++ b/src/app/organizations/tools/import.component.ts @@ -0,0 +1,78 @@ +import { Component } from '@angular/core'; +import { + ActivatedRoute, + Router, +} from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { Importer } from 'jslib/importers/importer'; + +import { CipherRequest } from 'jslib/models/request/cipherRequest'; +import { CollectionRequest } from 'jslib/models/request/collectionRequest'; +import { ImportOrganizationCiphersRequest } from 'jslib/models/request/importOrganizationCiphersRequest'; +import { KvpRequest } from 'jslib/models/request/kvpRequest'; + +import { ImportResult } from 'jslib/models/domain/importResult'; + +import { ImportComponent as BaseImportComponent } from '../../tools/import.component'; + +@Component({ + selector: 'app-org-import', + templateUrl: '../../tools/import.component.html', +}) +export class ImportComponent extends BaseImportComponent { + organizationId: string; + + constructor(i18nService: I18nService, analytics: Angulartics2, + toasterService: ToasterService, cipherService: CipherService, + folderService: FolderService, apiService: ApiService, + router: Router, private collectionService: CollectionService, + private route: ActivatedRoute) { + super(i18nService, analytics, toasterService, cipherService, folderService, apiService, router); + } + + ngOnInit() { + this.route.parent.parent.params.subscribe(async (params) => { + this.organizationId = params.organizationId; + this.successNavigate = ['organizations', this.organizationId, 'vault']; + super.ngOnInit(); + }); + } + + protected async postImport(importResult: ImportResult) { + const request = new ImportOrganizationCiphersRequest(); + for (let i = 0; i < importResult.ciphers.length; i++) { + importResult.ciphers[i].organizationId = this.organizationId; + const c = await this.cipherService.encrypt(importResult.ciphers[i]); + request.ciphers.push(new CipherRequest(c)); + } + if (importResult.collections != null) { + for (let i = 0; i < importResult.collections.length; i++) { + importResult.collections[i].organizationId = this.organizationId; + const c = await this.collectionService.encrypt(importResult.collections[i]); + request.collections.push(new CollectionRequest(c)); + } + } + if (importResult.collectionRelationships != null) { + importResult.collectionRelationships.forEach((v: number, k: number) => + request.collectionRelationships.push(new KvpRequest(k, v))); + } + return await this.apiService.postImportOrganizationCiphers(this.organizationId, request); + } + + protected getImporter(): Importer { + const importer = super.getImporter(); + if (importer != null) { + importer.organization = true; + } + return importer; + } +} diff --git a/src/app/organizations/tools/tools.component.html b/src/app/organizations/tools/tools.component.html new file mode 100644 index 0000000000..5b2d2ba79b --- /dev/null +++ b/src/app/organizations/tools/tools.component.html @@ -0,0 +1,20 @@ +
+
+ +
+ +
+
+
diff --git a/src/app/organizations/tools/tools.component.ts b/src/app/organizations/tools/tools.component.ts new file mode 100644 index 0000000000..3aa3be4b55 --- /dev/null +++ b/src/app/organizations/tools/tools.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-org-tools', + templateUrl: 'tools.component.html', +}) +export class ToolsComponent { } diff --git a/src/app/organizations/vault/add-edit.component.ts b/src/app/organizations/vault/add-edit.component.ts new file mode 100644 index 0000000000..9a23bc9321 --- /dev/null +++ b/src/app/organizations/vault/add-edit.component.ts @@ -0,0 +1,77 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { AuditService } from 'jslib/abstractions/audit.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { StateService } from 'jslib/abstractions/state.service'; +import { TokenService } from 'jslib/abstractions/token.service'; +import { TotpService } from 'jslib/abstractions/totp.service'; + +import { CipherData } from 'jslib/models/data/cipherData'; +import { Cipher } from 'jslib/models/domain/cipher'; +import { Organization } from 'jslib/models/domain/organization'; +import { CipherRequest } from 'jslib/models/request/cipherRequest'; + +import { AddEditComponent as BaseAddEditComponent } from '../../vault/add-edit.component'; + +@Component({ + selector: 'app-org-vault-add-edit', + templateUrl: '../../vault/add-edit.component.html', +}) +export class AddEditComponent extends BaseAddEditComponent implements OnInit { + organization: Organization; + + constructor(cipherService: CipherService, folderService: FolderService, + i18nService: I18nService, platformUtilsService: PlatformUtilsService, + analytics: Angulartics2, toasterService: ToasterService, + auditService: AuditService, stateService: StateService, + tokenService: TokenService, totpService: TotpService, + passwordGenerationService: PasswordGenerationService, private apiService: ApiService) { + super(cipherService, folderService, i18nService, platformUtilsService, analytics, + toasterService, auditService, stateService, tokenService, totpService, passwordGenerationService); + } + + protected async loadCipher() { + if (!this.organization.isAdmin) { + return await super.loadCipher(); + } + const response = await this.apiService.getCipherAdmin(this.cipherId); + return new Cipher(new CipherData(response)); + } + + protected encryptCipher() { + if (!this.editMode) { + this.cipher.organizationId = this.organization.id; + } + return super.encryptCipher(); + } + + protected async saveCipher(cipher: Cipher) { + if (!this.organization.isAdmin) { + return super.saveCipher(cipher); + } + const request = new CipherRequest(cipher); + if (this.editMode) { + return this.apiService.putCipherAdmin(this.cipherId, request); + } else { + return this.apiService.postCipherAdmin(request); + } + } + + protected async deleteCipher() { + if (!this.organization.isAdmin) { + return super.deleteCipher(); + } + return this.apiService.deleteCipherAdmin(this.cipherId); + } +} diff --git a/src/app/organizations/vault/attachments.component.ts b/src/app/organizations/vault/attachments.component.ts new file mode 100644 index 0000000000..de1021e2cc --- /dev/null +++ b/src/app/organizations/vault/attachments.component.ts @@ -0,0 +1,52 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { TokenService } from 'jslib/abstractions/token.service'; + +import { CipherData } from 'jslib/models/data/cipherData'; +import { Cipher } from 'jslib/models/domain/cipher'; +import { Organization } from 'jslib/models/domain/organization'; + +import { AttachmentsComponent as BaseAttachmentsComponent } from '../../vault/attachments.component'; + +@Component({ + selector: 'app-org-vault-attachments', + templateUrl: '../../vault/attachments.component.html', +}) +export class AttachmentsComponent extends BaseAttachmentsComponent { + organization: Organization; + + constructor(cipherService: CipherService, analytics: Angulartics2, + toasterService: ToasterService, i18nService: I18nService, + cryptoService: CryptoService, tokenService: TokenService, + platformUtilsService: PlatformUtilsService, private apiService: ApiService) { + super(cipherService, analytics, toasterService, i18nService, cryptoService, tokenService, + platformUtilsService); + } + + protected async loadCipher() { + if (!this.organization.isAdmin) { + return await super.loadCipher(); + } + const response = await this.apiService.getCipherAdmin(this.cipherId); + return new Cipher(new CipherData(response)); + } + + protected saveCipherAttachment(file: File) { + return this.cipherService.saveAttachmentWithServer(this.cipherDomain, file, this.organization.isAdmin); + } + + protected deleteCipherAttachment(attachmentId: string) { + if (!this.organization.isAdmin) { + return super.deleteCipherAttachment(attachmentId); + } + return this.apiService.deleteCipherAttachmentAdmin(this.cipherId, attachmentId); + } +} diff --git a/src/app/organizations/vault/ciphers.component.ts b/src/app/organizations/vault/ciphers.component.ts new file mode 100644 index 0000000000..30e6f12ddd --- /dev/null +++ b/src/app/organizations/vault/ciphers.component.ts @@ -0,0 +1,67 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { CipherData } from 'jslib/models/data/cipherData'; +import { Cipher } from 'jslib/models/domain/cipher'; +import { Organization } from 'jslib/models/domain/organization'; +import { CipherView } from 'jslib/models/view/cipherView'; + +import { CiphersComponent as BaseCiphersComponent } from '../../vault/ciphers.component'; + +@Component({ + selector: 'app-org-vault-ciphers', + templateUrl: '../../vault/ciphers.component.html', +}) +export class CiphersComponent extends BaseCiphersComponent { + organization: Organization; + + constructor(cipherService: CipherService, analytics: Angulartics2, + toasterService: ToasterService, i18nService: I18nService, + platformUtilsService: PlatformUtilsService, private apiService: ApiService) { + super(cipherService, analytics, toasterService, i18nService, platformUtilsService); + } + + async load(filter: (cipher: CipherView) => boolean = null) { + if (!this.organization.isAdmin) { + await super.load(); + return; + } + const ciphers = await this.apiService.getCiphersOrganization(this.organization.id); + if (ciphers != null && ciphers.data != null && ciphers.data.length) { + const decCiphers: CipherView[] = []; + const promises: any[] = []; + ciphers.data.forEach((r) => { + const data = new CipherData(r); + const cipher = new Cipher(data); + promises.push(cipher.decrypt().then((c) => decCiphers.push(c))); + }); + await Promise.all(promises); + decCiphers.sort(this.cipherService.getLocaleSortingFunction()); + this.allCiphers = decCiphers; + } else { + this.allCiphers = []; + } + this.applyFilter(filter); + this.loaded = true; + } + + applyFilter(filter: (cipher: CipherView) => boolean = null) { + if (this.organization.isAdmin) { + super.applyFilter(filter); + } else { + const f = (c: CipherView) => c.organizationId === this.organization.id && (filter == null || filter(c)); + super.applyFilter(f); + } + } + + checkCipher(c: CipherView) { + // do nothing + } +} diff --git a/src/app/organizations/vault/collections.component.ts b/src/app/organizations/vault/collections.component.ts new file mode 100644 index 0000000000..671c45acfc --- /dev/null +++ b/src/app/organizations/vault/collections.component.ts @@ -0,0 +1,57 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { CipherData } from 'jslib/models/data/cipherData'; +import { Cipher } from 'jslib/models/domain/cipher'; +import { Organization } from 'jslib/models/domain/organization'; +import { CipherCollectionsRequest } from 'jslib/models/request/cipherCollectionsRequest'; + +import { CollectionsComponent as BaseCollectionsComponent } from '../../vault/collections.component'; + +@Component({ + selector: 'app-org-vault-collections', + templateUrl: '../../vault/collections.component.html', +}) +export class CollectionsComponent extends BaseCollectionsComponent { + organization: Organization; + + constructor(collectionService: CollectionService, analytics: Angulartics2, + toasterService: ToasterService, i18nService: I18nService, + cipherService: CipherService, private apiService: ApiService) { + super(collectionService, analytics, toasterService, i18nService, cipherService); + } + + protected async loadCipher() { + if (!this.organization.isAdmin) { + return await super.loadCipher(); + } + const response = await this.apiService.getCipherAdmin(this.cipherId); + return new Cipher(new CipherData(response)); + } + + protected loadCipherCollections() { + if (!this.organization.isAdmin) { + return super.loadCipherCollections(); + } + return this.collectionIds; + } + + protected loadCollections() { + if (!this.organization.isAdmin) { + return super.loadCollections(); + } + return Promise.resolve(this.collections); + } + + protected saveCollections() { + const request = new CipherCollectionsRequest(this.cipherDomain.collectionIds); + return this.apiService.putCipherCollectionsAdmin(this.cipherId, request); + } +} diff --git a/src/app/organizations/vault/groupings.component.ts b/src/app/organizations/vault/groupings.component.ts new file mode 100644 index 0000000000..6b853fe954 --- /dev/null +++ b/src/app/organizations/vault/groupings.component.ts @@ -0,0 +1,49 @@ +import { Component } from '@angular/core'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { CollectionData } from 'jslib/models/data/collectionData'; +import { Collection } from 'jslib/models/domain/collection'; +import { Organization } from 'jslib/models/domain/organization'; +import { CollectionDetailsResponse } from 'jslib/models/response/collectionResponse'; +import { CollectionView } from 'jslib/models/view/collectionView'; + +import { GroupingsComponent as BaseGroupingsComponent } from '../../vault/groupings.component'; + +@Component({ + selector: 'app-org-vault-groupings', + templateUrl: '../../vault/groupings.component.html', +}) +export class GroupingsComponent extends BaseGroupingsComponent { + organization: Organization; + + constructor(collectionService: CollectionService, folderService: FolderService, + private apiService: ApiService, private i18nService: I18nService) { + super(collectionService, folderService); + } + + async loadCollections() { + if (!this.organization.isAdmin) { + await super.loadCollections(this.organization.id); + return; + } + const collections = await this.apiService.getCollections(this.organization.id); + if (collections != null && collections.data != null && collections.data.length) { + const collectionDomains = collections.data.map((r) => + new Collection(new CollectionData(r as CollectionDetailsResponse))); + this.collections = await this.collectionService.decryptMany(collectionDomains); + } else { + this.collections = []; + } + + const unassignedCollection = new CollectionView(); + unassignedCollection.name = this.i18nService.t('unassigned'); + unassignedCollection.id = 'unassigned'; + unassignedCollection.organizationId = this.organization.id; + unassignedCollection.readOnly = true; + this.collections.push(unassignedCollection); + } +} diff --git a/src/app/organizations/vault/vault.component.html b/src/app/organizations/vault/vault.component.html new file mode 100644 index 0000000000..8a4aa67025 --- /dev/null +++ b/src/app/organizations/vault/vault.component.html @@ -0,0 +1,23 @@ +
+
+
+ + +
+
+ + + +
+
+
+ + + diff --git a/src/app/organizations/vault/vault.component.ts b/src/app/organizations/vault/vault.component.ts new file mode 100644 index 0000000000..3d4ec131ff --- /dev/null +++ b/src/app/organizations/vault/vault.component.ts @@ -0,0 +1,230 @@ +import { Location } from '@angular/common'; +import { + Component, + ComponentFactoryResolver, + OnInit, + ViewChild, + ViewContainerRef, +} from '@angular/core'; +import { + ActivatedRoute, + Router, +} from '@angular/router'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { Organization } from 'jslib/models/domain/organization'; +import { CipherView } from 'jslib/models/view/cipherView'; + +import { CipherType } from 'jslib/enums/cipherType'; + +import { ModalComponent } from '../../modal.component'; + +import { AddEditComponent } from './add-edit.component'; +import { AttachmentsComponent } from './attachments.component'; +import { CiphersComponent } from './ciphers.component'; +import { CollectionsComponent } from './collections.component'; +import { GroupingsComponent } from './groupings.component'; + +@Component({ + selector: 'app-org-vault', + templateUrl: 'vault.component.html', +}) +export class VaultComponent implements OnInit { + @ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent; + @ViewChild(CiphersComponent) ciphersComponent: CiphersComponent; + @ViewChild('attachments', { read: ViewContainerRef }) attachmentsModalRef: ViewContainerRef; + @ViewChild('cipherAddEdit', { read: ViewContainerRef }) cipherAddEditModalRef: ViewContainerRef; + @ViewChild('collections', { read: ViewContainerRef }) collectionsModalRef: ViewContainerRef; + + organization: Organization; + collectionId: string; + type: CipherType; + + private modal: ModalComponent = null; + + constructor(private route: ActivatedRoute, private userService: UserService, + private location: Location, private router: Router, + private syncService: SyncService, private i18nService: I18nService, + private componentFactoryResolver: ComponentFactoryResolver) { } + + ngOnInit() { + this.route.parent.params.subscribe(async (params) => { + this.organization = await this.userService.getOrganization(params.organizationId); + this.groupingsComponent.organization = this.organization; + this.ciphersComponent.organization = this.organization; + + this.route.queryParams.subscribe(async (qParams) => { + if (!this.organization.isAdmin) { + await this.syncService.fullSync(false); + } + await this.groupingsComponent.load(); + + if (qParams == null) { + this.groupingsComponent.selectedAll = true; + await this.ciphersComponent.load(); + return; + } + + if (qParams.type) { + const t = parseInt(qParams.type, null); + this.groupingsComponent.selectedType = t; + await this.filterCipherType(t, true); + } else if (qParams.collectionId) { + this.groupingsComponent.selectedCollectionId = qParams.collectionId; + await this.filterCollection(qParams.collectionId, true); + } else { + this.groupingsComponent.selectedAll = true; + await this.ciphersComponent.load(); + } + }); + }); + } + + async clearGroupingFilters() { + this.ciphersComponent.showAddNew = true; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchVault'); + await this.ciphersComponent.applyFilter(); + this.clearFilters(); + this.go(); + } + + async filterCipherType(type: CipherType, load = false) { + this.ciphersComponent.showAddNew = true; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchType'); + const filter = (c: CipherView) => c.type === type; + if (load) { + await this.ciphersComponent.load(filter); + } else { + await this.ciphersComponent.applyFilter(filter); + } + this.clearFilters(); + this.type = type; + this.go(); + } + + async filterCollection(collectionId: string, load = false) { + this.ciphersComponent.showAddNew = false; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchCollection'); + const filter = (c: CipherView) => { + if (collectionId === 'unassigned') { + return c.collectionIds == null || c.collectionIds.length === 0; + } else { + return c.collectionIds.indexOf(collectionId) > -1; + } + }; + if (load) { + await this.ciphersComponent.load(filter); + } else { + await this.ciphersComponent.applyFilter(filter); + } + this.clearFilters(); + this.collectionId = collectionId; + this.go(); + } + + filterSearchText(searchText: string) { + this.ciphersComponent.searchText = searchText; + } + + editCipherAttachments(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.attachmentsModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(AttachmentsComponent, this.attachmentsModalRef); + + childComponent.organization = this.organization; + childComponent.cipherId = cipher.id; + let madeAttachmentChanges = false; + childComponent.onUploadedAttachment.subscribe(() => madeAttachmentChanges = true); + childComponent.onDeletedAttachment.subscribe(() => madeAttachmentChanges = true); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + if (madeAttachmentChanges) { + await this.ciphersComponent.refresh(); + } + madeAttachmentChanges = false; + }); + } + + editCipherCollections(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.collectionsModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(CollectionsComponent, this.collectionsModalRef); + + if (this.organization.isAdmin) { + childComponent.collectionIds = cipher.collectionIds; + childComponent.collections = this.groupingsComponent.collections.filter((c) => !c.readOnly); + } + childComponent.organization = this.organization; + childComponent.cipherId = cipher.id; + childComponent.onSavedCollections.subscribe(async () => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + addCipher() { + const component = this.editCipher(null); + component.type = this.type; + } + + editCipher(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.cipherAddEditModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(AddEditComponent, this.cipherAddEditModalRef); + + childComponent.organization = this.organization; + childComponent.cipherId = cipher == null ? null : cipher.id; + childComponent.onSavedCipher.subscribe(async (c: CipherView) => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + childComponent.onDeletedCipher.subscribe(async (c: CipherView) => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + + return childComponent; + } + + private clearFilters() { + this.collectionId = null; + this.type = null; + } + + private go(queryParams: any = null) { + if (queryParams == null) { + queryParams = { + type: this.type, + collectionId: this.collectionId, + }; + } + + const url = this.router.createUrlTree(['organizations', this.organization.id, 'vault'], + { queryParams: queryParams }).toString(); + this.location.go(url); + } +} diff --git a/src/app/polyfills.ts b/src/app/polyfills.ts new file mode 100644 index 0000000000..c0d0ee3685 --- /dev/null +++ b/src/app/polyfills.ts @@ -0,0 +1,17 @@ +/* tslint:disable */ +import 'core-js/es6'; +import 'core-js/es7/reflect'; +require('zone.js/dist/zone'); + +if (process.env.ENV === 'production') { + // Production +} else { + // Development and test + Error['stackTraceLimit'] = Infinity; + require('zone.js/dist/long-stack-trace-zone'); +} + +// Other polyfills +require('whatwg-fetch'); +require('webcrypto-shim'); +/* tslint:enable */ diff --git a/src/app/reports/reportsBreachController.js b/src/app/reports/reportsBreachController.js deleted file mode 100644 index ddcb86c0d2..0000000000 --- a/src/app/reports/reportsBreachController.js +++ /dev/null @@ -1,38 +0,0 @@ -angular - .module('bit.tools') - - .controller('reportsBreachController', function ($scope, apiService, toastr, authService) { - $scope.loading = true; - $scope.error = false; - $scope.breachAccounts = []; - $scope.email = null; - - $scope.$on('$viewContentLoaded', function () { - authService.getUserProfile().then(function (userProfile) { - $scope.email = userProfile.email; - return apiService.hibp.get({ email: $scope.email }).$promise; - }).then(function (response) { - var breachAccounts = []; - for (var i = 0; i < response.length; i++) { - var breach = { - id: response[i].Name, - title: response[i].Title, - domain: response[i].Domain, - date: new Date(response[i].BreachDate), - reportedDate: new Date(response[i].AddedDate), - modifiedDate: new Date(response[i].ModifiedDate), - count: response[i].PwnCount, - description: response[i].Description, - classes: response[i].DataClasses, - image: 'https://haveibeenpwned.com/Content/Images/PwnedLogos/' + response[i].Name + '.' + response[i].LogoType - }; - breachAccounts.push(breach); - } - $scope.breachAccounts = breachAccounts; - $scope.loading = false; - }, function (response) { - $scope.error = response.status !== 404; - $scope.loading = false; - }); - }); - }); diff --git a/src/app/reports/reportsModule.js b/src/app/reports/reportsModule.js deleted file mode 100644 index 1ccbf4d588..0000000000 --- a/src/app/reports/reportsModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.reports', ['toastr', 'ngSanitize']); diff --git a/src/app/reports/views/reportsBreach.html b/src/app/reports/views/reportsBreach.html deleted file mode 100644 index f4dc4732eb..0000000000 --- a/src/app/reports/views/reportsBreach.html +++ /dev/null @@ -1,74 +0,0 @@ -
-

- Data Breach Report - have you been pwned? -

-
-
-
-

Loading...

-
-
-

An error occurred trying to load the report. Try again...

-
-
-

Oh No, Data Breaches Found!

-

- Your email ({{email}}) was found in {{breachAccounts.length}} - different data - - online. -

-

- A "breach" is an incident where a site's data has been illegally accessed by hackers and then released publicly. - Review the types of data that were compromised (email addresses, passwords, credit cards etc.) and take appropriate - action, such as changing passwords. -

- Check another email -
-
-

Good News, Nothing Found!

-

Your email ({{email}}) was not found in any known data breaches.

- Check another email -
-
-
-

{{breach.title}}

-
-
-
-
- {{breach.id}} logo -
-
-
-
-

-
Compromised Data
-
    -
  • {{class}}
  • -
-
-
-
-
-
{{breach.domain}}
-
Users
-
{{breach.count | number: 0}}
-
Occurred
-
{{breach.date | date: format: mediumDate}}
-
Reported
-
{{breach.reportedDate | date: format: mediumDate}}
-
Updated
-
{{breach.modifiedDate | date: format: mediumDate}}
-
-
-
-
-
-
-
- This data is brought to you as a service from - Have I been pwned?. - Please check out their wonderful services and subscribe to receive notifications about future data breaches. -
diff --git a/src/app/services/apiService.js b/src/app/services/apiService.js deleted file mode 100644 index 99a122384d..0000000000 --- a/src/app/services/apiService.js +++ /dev/null @@ -1,222 +0,0 @@ -angular - .module('bit.services') - - .factory('apiService', function ($resource, tokenService, appSettings, $httpParamSerializer, utilsService) { - var _service = {}, - _apiUri = appSettings.apiUri, - _identityUri = appSettings.identityUri; - - _service.folders = $resource(_apiUri + '/folders/:id', {}, { - get: { method: 'GET', params: { id: '@id' } }, - list: { method: 'GET', params: {} }, - post: { method: 'POST', params: {} }, - put: { method: 'POST', params: { id: '@id' } }, - del: { url: _apiUri + '/folders/:id/delete', method: 'POST', params: { id: '@id' } } - }); - - _service.ciphers = $resource(_apiUri + '/ciphers/:id', {}, { - get: { method: 'GET', params: { id: '@id' } }, - getAdmin: { url: _apiUri + '/ciphers/:id/admin', method: 'GET', params: { id: '@id' } }, - getDetails: { url: _apiUri + '/ciphers/:id/details', method: 'GET', params: { id: '@id' } }, - list: { method: 'GET', params: {} }, - listOrganizationDetails: { url: _apiUri + '/ciphers/organization-details', method: 'GET', params: {} }, - post: { method: 'POST', params: {} }, - postAdmin: { url: _apiUri + '/ciphers/admin', method: 'POST', params: {} }, - put: { method: 'POST', params: { id: '@id' } }, - putAdmin: { url: _apiUri + '/ciphers/:id/admin', method: 'POST', params: { id: '@id' } }, - 'import': { url: _apiUri + '/ciphers/import', method: 'POST', params: {} }, - importOrg: { url: _apiUri + '/ciphers/import-organization?organizationId=:orgId', method: 'POST', params: { orgId: '@orgId' } }, - putPartial: { url: _apiUri + '/ciphers/:id/partial', method: 'POST', params: { id: '@id' } }, - putShare: { url: _apiUri + '/ciphers/:id/share', method: 'POST', params: { id: '@id' } }, - putCollections: { url: _apiUri + '/ciphers/:id/collections', method: 'POST', params: { id: '@id' } }, - putCollectionsAdmin: { url: _apiUri + '/ciphers/:id/collections-admin', method: 'POST', params: { id: '@id' } }, - del: { url: _apiUri + '/ciphers/:id/delete', method: 'POST', params: { id: '@id' } }, - delAdmin: { url: _apiUri + '/ciphers/:id/delete-admin', method: 'POST', params: { id: '@id' } }, - delMany: { url: _apiUri + '/ciphers/delete', method: 'POST' }, - moveMany: { url: _apiUri + '/ciphers/move', method: 'POST' }, - purge: { url: _apiUri + '/ciphers/purge', method: 'POST' }, - postAttachment: { - url: _apiUri + '/ciphers/:id/attachment', - method: 'POST', - headers: { 'Content-Type': undefined }, - params: { id: '@id' } - }, - postAttachmentAdmin: { - url: _apiUri + '/ciphers/:id/attachment-admin', - method: 'POST', - headers: { 'Content-Type': undefined }, - params: { id: '@id' } - }, - postShareAttachment: { - url: _apiUri + '/ciphers/:id/attachment/:attachmentId/share?organizationId=:orgId', - method: 'POST', - headers: { 'Content-Type': undefined }, - params: { id: '@id', attachmentId: '@attachmentId', orgId: '@orgId' } - }, - delAttachment: { url: _apiUri + '/ciphers/:id/attachment/:attachmentId/delete', method: 'POST', params: { id: '@id', attachmentId: '@attachmentId' } }, - delAttachmentAdmin: { url: _apiUri + '/ciphers/:id/attachment/:attachmentId/delete-admin', method: 'POST', params: { id: '@id', attachmentId: '@attachmentId' } } - }); - - _service.organizations = $resource(_apiUri + '/organizations/:id', {}, { - get: { method: 'GET', params: { id: '@id' } }, - getBilling: { url: _apiUri + '/organizations/:id/billing', method: 'GET', params: { id: '@id' } }, - getLicense: { url: _apiUri + '/organizations/:id/license', method: 'GET', params: { id: '@id' } }, - list: { method: 'GET', params: {} }, - post: { method: 'POST', params: {} }, - put: { method: 'POST', params: { id: '@id' } }, - putPayment: { url: _apiUri + '/organizations/:id/payment', method: 'POST', params: { id: '@id' } }, - putSeat: { url: _apiUri + '/organizations/:id/seat', method: 'POST', params: { id: '@id' } }, - putStorage: { url: _apiUri + '/organizations/:id/storage', method: 'POST', params: { id: '@id' } }, - putUpgrade: { url: _apiUri + '/organizations/:id/upgrade', method: 'POST', params: { id: '@id' } }, - putCancel: { url: _apiUri + '/organizations/:id/cancel', method: 'POST', params: { id: '@id' } }, - putReinstate: { url: _apiUri + '/organizations/:id/reinstate', method: 'POST', params: { id: '@id' } }, - postLeave: { url: _apiUri + '/organizations/:id/leave', method: 'POST', params: { id: '@id' } }, - postVerifyBank: { url: _apiUri + '/organizations/:id/verify-bank', method: 'POST', params: { id: '@id' } }, - del: { url: _apiUri + '/organizations/:id/delete', method: 'POST', params: { id: '@id' } }, - postLicense: { - url: _apiUri + '/organizations/license', - method: 'POST', - headers: { 'Content-Type': undefined } - }, - putLicense: { - url: _apiUri + '/organizations/:id/license', - method: 'POST', - headers: { 'Content-Type': undefined } - } - }); - - _service.organizationUsers = $resource(_apiUri + '/organizations/:orgId/users/:id', {}, { - get: { method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - list: { method: 'GET', params: { orgId: '@orgId' } }, - listGroups: { url: _apiUri + '/organizations/:orgId/users/:id/groups', method: 'GET', params: { id: '@id', orgId: '@orgId' }, isArray: true }, - invite: { url: _apiUri + '/organizations/:orgId/users/invite', method: 'POST', params: { orgId: '@orgId' } }, - reinvite: { url: _apiUri + '/organizations/:orgId/users/:id/reinvite', method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - accept: { url: _apiUri + '/organizations/:orgId/users/:id/accept', method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - confirm: { url: _apiUri + '/organizations/:orgId/users/:id/confirm', method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - put: { method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - putGroups: { url: _apiUri + '/organizations/:orgId/users/:id/groups', method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - del: { url: _apiUri + '/organizations/:orgId/users/:id/delete', method: 'POST', params: { id: '@id', orgId: '@orgId' } } - }); - - _service.collections = $resource(_apiUri + '/organizations/:orgId/collections/:id', {}, { - get: { method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - getDetails: { url: _apiUri + '/organizations/:orgId/collections/:id/details', method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - listMe: { url: _apiUri + '/collections?writeOnly=:writeOnly', method: 'GET', params: { writeOnly: '@writeOnly' } }, - listOrganization: { method: 'GET', params: { orgId: '@orgId' } }, - listUsers: { url: _apiUri + '/organizations/:orgId/collections/:id/users', method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - post: { method: 'POST', params: { orgId: '@orgId' } }, - put: { method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - del: { url: _apiUri + '/organizations/:orgId/collections/:id/delete', method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - delUser: { url: _apiUri + '/organizations/:orgId/collections/:id/delete-user/:orgUserId', method: 'POST', params: { id: '@id', orgId: '@orgId', orgUserId: '@orgUserId' } } - }); - - _service.groups = $resource(_apiUri + '/organizations/:orgId/groups/:id', {}, { - get: { method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - getDetails: { url: _apiUri + '/organizations/:orgId/groups/:id/details', method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - listOrganization: { method: 'GET', params: { orgId: '@orgId' } }, - listUsers: { url: _apiUri + '/organizations/:orgId/groups/:id/users', method: 'GET', params: { id: '@id', orgId: '@orgId' } }, - post: { method: 'POST', params: { orgId: '@orgId' } }, - put: { method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - del: { url: _apiUri + '/organizations/:orgId/groups/:id/delete', method: 'POST', params: { id: '@id', orgId: '@orgId' } }, - delUser: { url: _apiUri + '/organizations/:orgId/groups/:id/delete-user/:orgUserId', method: 'POST', params: { id: '@id', orgId: '@orgId', orgUserId: '@orgUserId' } } - }); - - _service.accounts = $resource(_apiUri + '/accounts', {}, { - register: { url: _apiUri + '/accounts/register', method: 'POST', params: {} }, - emailToken: { url: _apiUri + '/accounts/email-token', method: 'POST', params: {} }, - email: { url: _apiUri + '/accounts/email', method: 'POST', params: {} }, - verifyEmailToken: { url: _apiUri + '/accounts/verify-email-token', method: 'POST', params: {} }, - verifyEmail: { url: _apiUri + '/accounts/verify-email', method: 'POST', params: {} }, - postDeleteRecoverToken: { url: _apiUri + '/accounts/delete-recover-token', method: 'POST', params: {} }, - postDeleteRecover: { url: _apiUri + '/accounts/delete-recover', method: 'POST', params: {} }, - putPassword: { url: _apiUri + '/accounts/password', method: 'POST', params: {} }, - getProfile: { url: _apiUri + '/accounts/profile', method: 'GET', params: {} }, - putProfile: { url: _apiUri + '/accounts/profile', method: 'POST', params: {} }, - getDomains: { url: _apiUri + '/accounts/domains', method: 'GET', params: {} }, - putDomains: { url: _apiUri + '/accounts/domains', method: 'POST', params: {} }, - postPasswordHint: { url: _apiUri + '/accounts/password-hint', method: 'POST', params: {} }, - putSecurityStamp: { url: _apiUri + '/accounts/security-stamp', method: 'POST', params: {} }, - putKeys: { url: _apiUri + '/accounts/keys', method: 'POST', params: {} }, - putKey: { url: _apiUri + '/accounts/key', method: 'POST', params: {} }, - 'import': { url: _apiUri + '/accounts/import', method: 'POST', params: {} }, - postDelete: { url: _apiUri + '/accounts/delete', method: 'POST', params: {} }, - putStorage: { url: _apiUri + '/accounts/storage', method: 'POST', params: {} }, - putPayment: { url: _apiUri + '/accounts/payment', method: 'POST', params: {} }, - putCancelPremium: { url: _apiUri + '/accounts/cancel-premium', method: 'POST', params: {} }, - putReinstatePremium: { url: _apiUri + '/accounts/reinstate-premium', method: 'POST', params: {} }, - getBilling: { url: _apiUri + '/accounts/billing', method: 'GET', params: {} }, - postPremium: { - url: _apiUri + '/accounts/premium', - method: 'POST', - headers: { 'Content-Type': undefined } - }, - putLicense: { - url: _apiUri + '/accounts/license', - method: 'POST', - headers: { 'Content-Type': undefined } - } - }); - - _service.twoFactor = $resource(_apiUri + '/two-factor', {}, { - list: { method: 'GET', params: {} }, - listOrganization: { url: _apiUri + '/organizations/:orgId/two-factor', method: 'GET', params: { orgId: '@orgId' } }, - getEmail: { url: _apiUri + '/two-factor/get-email', method: 'POST', params: {} }, - getU2f: { url: _apiUri + '/two-factor/get-u2f', method: 'POST', params: {} }, - getDuo: { url: _apiUri + '/two-factor/get-duo', method: 'POST', params: {} }, - getOrganizationDuo: { url: _apiUri + '/organizations/:orgId/two-factor/get-duo', method: 'POST', params: { orgId: '@orgId' } }, - getAuthenticator: { url: _apiUri + '/two-factor/get-authenticator', method: 'POST', params: {} }, - getYubi: { url: _apiUri + '/two-factor/get-yubikey', method: 'POST', params: {} }, - sendEmail: { url: _apiUri + '/two-factor/send-email', method: 'POST', params: {} }, - sendEmailLogin: { url: _apiUri + '/two-factor/send-email-login', method: 'POST', params: {} }, - putEmail: { url: _apiUri + '/two-factor/email', method: 'POST', params: {} }, - putU2f: { url: _apiUri + '/two-factor/u2f', method: 'POST', params: {} }, - putAuthenticator: { url: _apiUri + '/two-factor/authenticator', method: 'POST', params: {} }, - putDuo: { url: _apiUri + '/two-factor/duo', method: 'POST', params: {} }, - putOrganizationDuo: { url: _apiUri + '/organizations/:orgId/two-factor/duo', method: 'POST', params: { orgId: '@orgId' } }, - putYubi: { url: _apiUri + '/two-factor/yubikey', method: 'POST', params: {} }, - disable: { url: _apiUri + '/two-factor/disable', method: 'POST', params: {} }, - disableOrganization: { url: _apiUri + '/organizations/:orgId/two-factor/disable', method: 'POST', params: { orgId: '@orgId' } }, - recover: { url: _apiUri + '/two-factor/recover', method: 'POST', params: {} }, - getRecover: { url: _apiUri + '/two-factor/get-recover', method: 'POST', params: {} } - }); - - _service.settings = $resource(_apiUri + '/settings', {}, { - getDomains: { url: _apiUri + '/settings/domains', method: 'GET', params: {} }, - putDomains: { url: _apiUri + '/settings/domains', method: 'POST', params: {} }, - }); - - _service.users = $resource(_apiUri + '/users/:id', {}, { - getPublicKey: { url: _apiUri + '/users/:id/public-key', method: 'GET', params: { id: '@id' } } - }); - - _service.events = $resource(_apiUri + '/events', {}, { - list: { method: 'GET', params: {} }, - listOrganization: { url: _apiUri + '/organizations/:orgId/events', method: 'GET', params: { id: '@orgId' } }, - listCipher: { url: _apiUri + '/ciphers/:id/events', method: 'GET', params: { id: '@id' } }, - listOrganizationUser: { url: _apiUri + '/organizations/:orgId/users/:id/events', method: 'GET', params: { orgId: '@orgId', id: '@id' } } - }); - - _service.identity = $resource(_identityUri + '/connect', {}, { - token: { - url: _identityUri + '/connect/token', - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', - 'Device-Type': utilsService.getDeviceType() - }, - transformRequest: transformUrlEncoded, - skipAuthorization: true, - params: {} - } - }); - - _service.hibp = $resource('https://haveibeenpwned.com/api/v2/breachedaccount/:email', {}, { - get: { method: 'GET', params: { email: '@email' }, isArray: true }, - }); - - function transformUrlEncoded(data) { - return $httpParamSerializer(data); - } - - return _service; - }); diff --git a/src/app/services/authService.js b/src/app/services/authService.js deleted file mode 100644 index c69ec0cece..0000000000 --- a/src/app/services/authService.js +++ /dev/null @@ -1,259 +0,0 @@ -angular - .module('bit.services') - - .factory('authService', function (cryptoService, apiService, tokenService, $q, jwtHelper, $rootScope, constants) { - var _service = {}, - _userProfile = null; - - _service.logIn = function (email, masterPassword, token, provider, remember) { - email = email.toLowerCase(); - - var deferred = $q.defer(); - - var makeResult; - cryptoService.makeKeyAndHash(email, masterPassword).then(function (result) { - makeResult = result; - - var request = { - username: email, - password: result.hash, - grant_type: 'password', - scope: 'api offline_access', - client_id: 'web' - }; - - // TODO: device information one day? - - if (token && typeof (provider) !== 'undefined' && provider !== null) { - remember = remember || remember !== false; - - request.twoFactorToken = token; - request.twoFactorProvider = provider; - request.twoFactorRemember = remember ? '1' : '0'; - } - else if (tokenService.getTwoFactorToken(email)) { - request.twoFactorToken = tokenService.getTwoFactorToken(email); - request.twoFactorProvider = constants.twoFactorProvider.remember; - request.twoFactorRemember = '0'; - } - - return apiService.identity.token(request).$promise; - }).then(function (response) { - if (!response || !response.access_token) { - return; - } - - tokenService.setToken(response.access_token); - tokenService.setRefreshToken(response.refresh_token); - cryptoService.setKey(makeResult.key); - - if (response.TwoFactorToken) { - tokenService.setTwoFactorToken(response.TwoFactorToken, email); - } - - if (response.Key) { - cryptoService.setEncKey(response.Key, makeResult.key); - } - - if (response.PrivateKey) { - cryptoService.setPrivateKey(response.PrivateKey); - return true; - } - else { - return cryptoService.makeKeyPair(); - } - }).then(function (keyResults) { - if (keyResults === true) { - return; - } - - cryptoService.setPrivateKey(keyResults.privateKeyEnc); - return apiService.accounts.putKeys({ - publicKey: keyResults.publicKey, - encryptedPrivateKey: keyResults.privateKeyEnc - }).$promise; - }).then(function () { - return _service.setUserProfile(); - }).then(function () { - deferred.resolve(); - }, function (error) { - _service.logOut(); - - if (error.status === 400 && error.data.TwoFactorProviders2 && - Object.keys(error.data.TwoFactorProviders2).length) { - tokenService.clearTwoFactorToken(email); - deferred.resolve(error.data.TwoFactorProviders2); - } - else { - deferred.reject(error); - } - }); - - return deferred.promise; - }; - - _service.logOut = function () { - tokenService.clearTokens(); - cryptoService.clearKeys(); - $rootScope.vaultCiphers = $rootScope.vaultFolders = $rootScope.vaultCollections = null; - _userProfile = null; - }; - - _service.getUserProfile = function () { - if (!_userProfile) { - return _service.setUserProfile(); - } - - var deferred = $q.defer(); - deferred.resolve(_userProfile); - return deferred.promise; - }; - - var _setDeferred = null; - _service.setUserProfile = function () { - if (_setDeferred && _setDeferred.promise.$$state.status === 0) { - return _setDeferred.promise; - } - - _setDeferred = $q.defer(); - - var token = tokenService.getToken(); - if (!token) { - _setDeferred.reject(); - return _setDeferred.promise; - } - - apiService.accounts.getProfile({}, function (profile) { - _userProfile = { - id: profile.Id, - email: profile.Email, - emailVerified: profile.EmailVerified, - premium: profile.Premium, - extended: { - name: profile.Name, - twoFactorEnabled: profile.TwoFactorEnabled, - culture: profile.Culture - } - }; - - if (profile.Organizations) { - var orgs = {}; - for (var i = 0; i < profile.Organizations.length; i++) { - orgs[profile.Organizations[i].Id] = { - id: profile.Organizations[i].Id, - name: profile.Organizations[i].Name, - key: profile.Organizations[i].Key, - status: profile.Organizations[i].Status, - type: profile.Organizations[i].Type, - enabled: profile.Organizations[i].Enabled, - maxCollections: profile.Organizations[i].MaxCollections, - maxStorageGb: profile.Organizations[i].MaxStorageGb, - seats: profile.Organizations[i].Seats, - useGroups: profile.Organizations[i].UseGroups, - useDirectory: profile.Organizations[i].UseDirectory, - useEvents: profile.Organizations[i].UseEvents, - use2fa: profile.Organizations[i].Use2fa, - useTotp: profile.Organizations[i].UseTotp - }; - } - - _userProfile.organizations = orgs; - cryptoService.setOrgKeys(orgs); - _setDeferred.resolve(_userProfile); - } - }, function (error) { - _setDeferred.reject(error); - }); - - return _setDeferred.promise; - }; - - _service.addProfileOrganizationOwner = function (org, keyCt) { - return _service.getUserProfile().then(function (profile) { - if (profile) { - if (!profile.organizations) { - profile.organizations = {}; - } - - var o = { - id: org.Id, - name: org.Name, - key: keyCt, - status: 2, // 2 = Confirmed - type: 0, // 0 = Owner - enabled: true, - maxCollections: org.MaxCollections, - maxStorageGb: org.MaxStorageGb, - seats: org.Seats, - useGroups: org.UseGroups, - useDirectory: org.UseDirectory, - useEvents: org.UseEvents, - use2fa: org.Use2fa, - useTotp: org.UseTotp - }; - profile.organizations[o.id] = o; - - _userProfile = profile; - cryptoService.addOrgKey(o.id, o.key); - } - }); - }; - - _service.removeProfileOrganization = function (orgId) { - return _service.getUserProfile().then(function (profile) { - if (profile) { - if (profile.organizations && profile.organizations.hasOwnProperty(orgId)) { - delete profile.organizations[orgId]; - _userProfile = profile; - } - - cryptoService.clearOrgKey(orgId); - } - }); - }; - - _service.updateProfileOrganization = function (org) { - return _service.getUserProfile().then(function (profile) { - if (profile) { - if (profile.organizations && org.Id in profile.organizations) { - profile.organizations[org.Id].name = org.Name; - _userProfile = profile; - } - } - }); - }; - - _service.updateProfilePremium = function (isPremium) { - return _service.getUserProfile().then(function (profile) { - if (profile) { - profile.premium = isPremium; - _userProfile = profile; - } - }); - }; - - _service.isAuthenticated = function () { - return tokenService.getToken() !== null; - }; - - _service.refreshAccessToken = function () { - var refreshToken = tokenService.getRefreshToken(); - if (!refreshToken) { - return $q(function (resolve, reject) { - resolve(null); - }); - } - - return apiService.identity.token({ - grant_type: 'refresh_token', - client_id: 'web', - refresh_token: refreshToken - }).$promise.then(function (response) { - tokenService.setToken(response.access_token); - tokenService.setRefreshToken(response.refresh_token); - return response.access_token; - }, function (response) { }); - }; - - return _service; - }); diff --git a/src/app/services/cipherService.js b/src/app/services/cipherService.js deleted file mode 100644 index 97da93c2d1..0000000000 --- a/src/app/services/cipherService.js +++ /dev/null @@ -1,570 +0,0 @@ -angular - .module('bit.services') - - .factory('cipherService', function (cryptoService, apiService, $q, $window, constants, appSettings, $localStorage) { - var _service = { - disableWebsiteIcons: $localStorage.disableWebsiteIcons - }; - - _service.decryptCiphers = function (encryptedCiphers) { - if (!encryptedCiphers) throw "encryptedCiphers is undefined or null"; - - var unencryptedCiphers = []; - for (var i = 0; i < encryptedCiphers.length; i++) { - unencryptedCiphers.push(_service.decryptCipher(encryptedCiphers[i])); - } - - return unencryptedCiphers; - }; - - _service.decryptCipher = function (encryptedCipher) { - if (!encryptedCipher) throw "encryptedCipher is undefined or null"; - - var key = null; - if (encryptedCipher.OrganizationId) { - key = cryptoService.getOrgKey(encryptedCipher.OrganizationId); - } - - var cipher = { - id: encryptedCipher.Id, - organizationId: encryptedCipher.OrganizationId, - collectionIds: encryptedCipher.CollectionIds || [], - 'type': encryptedCipher.Type, - name: cryptoService.decrypt(encryptedCipher.Name, key), - notes: _service.decryptProperty(encryptedCipher.Notes, key, true, false), - fields: _service.decryptFields(key, encryptedCipher.Fields), - folderId: encryptedCipher.FolderId, - favorite: encryptedCipher.Favorite, - edit: encryptedCipher.Edit, - organizationUseTotp: encryptedCipher.OrganizationUseTotp, - attachments: null, - icon: null - }; - - var i; - switch (cipher.type) { - case constants.cipherType.login: - cipher.login = { - username: _service.decryptProperty(encryptedCipher.Login.Username, key, true, false), - password: _service.decryptProperty(encryptedCipher.Login.Password, key, true, false), - totp: _service.decryptProperty(encryptedCipher.Login.Totp, key, true, false), - uris: null - }; - if (encryptedCipher.Login.Uris) { - cipher.login.uris = []; - for (i = 0; i < encryptedCipher.Login.Uris.length; i++) { - cipher.login.uris.push({ - uri: _service.decryptProperty(encryptedCipher.Login.Uris[i].Uri, key, true, false), - match: encryptedCipher.Login.Uris[i].Match - }); - } - } - cipher.icon = 'fa-globe'; - break; - case constants.cipherType.secureNote: - cipher.secureNote = { - type: encryptedCipher.SecureNote.Type - }; - cipher.icon = 'fa-sticky-note-o'; - break; - case constants.cipherType.card: - cipher.card = { - cardholderName: _service.decryptProperty(encryptedCipher.Card.CardholderName, key, true, false), - number: _service.decryptProperty(encryptedCipher.Card.Number, key, true, false), - brand: _service.decryptProperty(encryptedCipher.Card.Brand, key, true, false), - expMonth: _service.decryptProperty(encryptedCipher.Card.ExpMonth, key, true, false), - expYear: _service.decryptProperty(encryptedCipher.Card.ExpYear, key, true, false), - code: _service.decryptProperty(encryptedCipher.Card.Code, key, true, false) - }; - cipher.icon = 'fa-credit-card'; - break; - case constants.cipherType.identity: - cipher.identity = { - title: _service.decryptProperty(encryptedCipher.Identity.Title, key, true, false), - firstName: _service.decryptProperty(encryptedCipher.Identity.FirstName, key, true, false), - middleName: _service.decryptProperty(encryptedCipher.Identity.MiddleName, key, true, false), - lastName: _service.decryptProperty(encryptedCipher.Identity.LastName, key, true, false), - address1: _service.decryptProperty(encryptedCipher.Identity.Address1, key, true, false), - address2: _service.decryptProperty(encryptedCipher.Identity.Address2, key, true, false), - address3: _service.decryptProperty(encryptedCipher.Identity.Address3, key, true, false), - city: _service.decryptProperty(encryptedCipher.Identity.City, key, true, false), - state: _service.decryptProperty(encryptedCipher.Identity.State, key, true, false), - postalCode: _service.decryptProperty(encryptedCipher.Identity.PostalCode, key, true, false), - country: _service.decryptProperty(encryptedCipher.Identity.Country, key, true, false), - company: _service.decryptProperty(encryptedCipher.Identity.Company, key, true, false), - email: _service.decryptProperty(encryptedCipher.Identity.Email, key, true, false), - phone: _service.decryptProperty(encryptedCipher.Identity.Phone, key, true, false), - ssn: _service.decryptProperty(encryptedCipher.Identity.SSN, key, true, false), - username: _service.decryptProperty(encryptedCipher.Identity.Username, key, true, false), - passportNumber: _service.decryptProperty(encryptedCipher.Identity.PassportNumber, key, true, false), - licenseNumber: _service.decryptProperty(encryptedCipher.Identity.LicenseNumber, key, true, false) - }; - cipher.icon = 'fa-id-card-o'; - break; - default: - break; - } - - if (!encryptedCipher.Attachments) { - return cipher; - } - - cipher.attachments = []; - for (i = 0; i < encryptedCipher.Attachments.length; i++) { - cipher.attachments.push(_service.decryptAttachment(key, encryptedCipher.Attachments[i])); - } - - return cipher; - }; - - _service.decryptCipherPreview = function (encryptedCipher) { - if (!encryptedCipher) throw "encryptedCipher is undefined or null"; - - var key = null; - if (encryptedCipher.OrganizationId) { - key = cryptoService.getOrgKey(encryptedCipher.OrganizationId); - } - - var cipher = { - id: encryptedCipher.Id, - organizationId: encryptedCipher.OrganizationId, - collectionIds: encryptedCipher.CollectionIds || [], - 'type': encryptedCipher.Type, - name: _service.decryptProperty(encryptedCipher.Name, key, false, true), - folderId: encryptedCipher.FolderId, - favorite: encryptedCipher.Favorite, - edit: encryptedCipher.Edit, - organizationUseTotp: encryptedCipher.OrganizationUseTotp, - hasAttachments: !!encryptedCipher.Attachments && encryptedCipher.Attachments.length > 0, - meta: {}, - icon: null - }; - - switch (cipher.type) { - case constants.cipherType.login: - cipher.subTitle = _service.decryptProperty(encryptedCipher.Login.Username, key, true, true); - cipher.meta.password = _service.decryptProperty(encryptedCipher.Login.Password, key, true, true); - cipher.meta.uri = null; - if (encryptedCipher.Login.Uris && encryptedCipher.Login.Uris.length) { - cipher.meta.uri = _service.decryptProperty(encryptedCipher.Login.Uris[0].Uri, key, true, true); - } - setLoginIcon(cipher, cipher.meta.uri, true); - break; - case constants.cipherType.secureNote: - cipher.subTitle = null; - cipher.icon = 'fa-sticky-note-o'; - break; - case constants.cipherType.card: - cipher.subTitle = ''; - cipher.meta.number = _service.decryptProperty(encryptedCipher.Card.Number, key, true, true); - var brand = _service.decryptProperty(encryptedCipher.Card.Brand, key, true, true); - if (brand) { - cipher.subTitle = brand; - } - if (cipher.meta.number && cipher.meta.number.length >= 4) { - if (cipher.subTitle !== '') { - cipher.subTitle += ', '; - } - cipher.subTitle += ('*' + cipher.meta.number.substr(cipher.meta.number.length - 4)); - } - cipher.icon = 'fa-credit-card'; - break; - case constants.cipherType.identity: - var firstName = _service.decryptProperty(encryptedCipher.Identity.FirstName, key, true, true); - var lastName = _service.decryptProperty(encryptedCipher.Identity.LastName, key, true, true); - cipher.subTitle = ''; - if (firstName) { - cipher.subTitle = firstName; - } - if (lastName) { - if (cipher.subTitle !== '') { - cipher.subTitle += ' '; - } - cipher.subTitle += lastName; - } - cipher.icon = 'fa-id-card-o'; - break; - default: - break; - } - - if (cipher.subTitle === '') { - cipher.subTitle = null; - } - - return cipher; - }; - - function setLoginIcon(cipher, uri, setImage) { - if (!_service.disableWebsiteIcons && uri) { - var hostnameUri = uri, - isWebsite = false; - - if (hostnameUri.indexOf('androidapp://') === 0) { - cipher.icon = 'fa-android'; - } - else if (hostnameUri.indexOf('iosapp://') === 0) { - cipher.icon = 'fa-apple'; - } - else if (hostnameUri.indexOf('://') === -1 && hostnameUri.indexOf('.') > -1) { - hostnameUri = "http://" + hostnameUri; - isWebsite = true; - } - else { - isWebsite = hostnameUri.indexOf('http') === 0 && hostnameUri.indexOf('.') > -1; - } - - if (setImage && isWebsite) { - try { - var url = new URL(hostnameUri); - cipher.meta.image = appSettings.iconsUri + '/' + url.hostname + '/icon.png'; - } - catch (e) { } - } - } - - if (!cipher.icon) { - cipher.icon = 'fa-globe'; - } - } - - _service.decryptAttachment = function (key, encryptedAttachment) { - if (!encryptedAttachment) throw "encryptedAttachment is undefined or null"; - - return { - id: encryptedAttachment.Id, - url: encryptedAttachment.Url, - fileName: cryptoService.decrypt(encryptedAttachment.FileName, key), - size: encryptedAttachment.SizeName - }; - }; - - _service.downloadAndDecryptAttachment = function (key, decryptedAttachment, openDownload) { - var deferred = $q.defer(); - var req = new XMLHttpRequest(); - req.open('GET', decryptedAttachment.url, true); - req.responseType = 'arraybuffer'; - req.onload = function (evt) { - if (!req.response) { - deferred.reject('No response'); - // error - return; - } - - cryptoService.decryptFromBytes(req.response, key).then(function (decBuf) { - if (openDownload) { - var blob = new Blob([decBuf]); - - // IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx - if ($window.navigator.msSaveOrOpenBlob) { - $window.navigator.msSaveBlob(blob, decryptedAttachment.fileName); - } - else { - var a = $window.document.createElement('a'); - a.href = $window.URL.createObjectURL(blob); - a.download = decryptedAttachment.fileName; - $window.document.body.appendChild(a); - a.click(); - $window.document.body.removeChild(a); - } - } - - deferred.resolve(new Uint8Array(decBuf)); - }); - }; - req.send(null); - return deferred.promise; - }; - - _service.decryptFields = function (key, encryptedFields) { - var unencryptedFields = []; - - if (encryptedFields) { - for (var i = 0; i < encryptedFields.length; i++) { - unencryptedFields.push(_service.decryptField(key, encryptedFields[i])); - } - } - - return unencryptedFields; - }; - - _service.decryptField = function (key, encryptedField) { - if (!encryptedField) throw "encryptedField is undefined or null"; - - return { - type: encryptedField.Type.toString(), - name: encryptedField.Name && encryptedField.Name !== '' ? cryptoService.decrypt(encryptedField.Name, key) : null, - value: encryptedField.Value && encryptedField.Value !== '' ? cryptoService.decrypt(encryptedField.Value, key) : null - }; - }; - - _service.decryptFolders = function (encryptedFolders) { - if (!encryptedFolders) throw "encryptedFolders is undefined or null"; - - var unencryptedFolders = []; - for (var i = 0; i < encryptedFolders.length; i++) { - unencryptedFolders.push(_service.decryptFolder(encryptedFolders[i])); - } - - return unencryptedFolders; - }; - - _service.decryptFolder = function (encryptedFolder) { - if (!encryptedFolder) throw "encryptedFolder is undefined or null"; - - return { - id: encryptedFolder.Id, - name: cryptoService.decrypt(encryptedFolder.Name) - }; - }; - - _service.decryptFolderPreview = function (encryptedFolder) { - if (!encryptedFolder) throw "encryptedFolder is undefined or null"; - - return { - id: encryptedFolder.Id, - name: _service.decryptProperty(encryptedFolder.Name, null, false, true) - }; - }; - - _service.decryptCollections = function (encryptedCollections, orgId, catchError) { - if (!encryptedCollections) throw "encryptedCollections is undefined or null"; - - var unencryptedCollections = []; - for (var i = 0; i < encryptedCollections.length; i++) { - unencryptedCollections.push(_service.decryptCollection(encryptedCollections[i], orgId, catchError)); - } - - return unencryptedCollections; - }; - - _service.decryptCollection = function (encryptedCollection, orgId, catchError) { - if (!encryptedCollection) throw "encryptedCollection is undefined or null"; - - catchError = catchError === true ? true : false; - orgId = orgId || encryptedCollection.OrganizationId; - var key = cryptoService.getOrgKey(orgId); - - return { - id: encryptedCollection.Id, - name: catchError ? _service.decryptProperty(encryptedCollection.Name, key, false, true) : - cryptoService.decrypt(encryptedCollection.Name, key) - }; - }; - - _service.decryptProperty = function (property, key, checkEmpty, showError) { - if (checkEmpty && (!property || property === '')) { - return null; - } - - try { - property = cryptoService.decrypt(property, key); - } - catch (err) { - property = null; - } - - return property || (showError ? '[error: cannot decrypt]' : null); - }; - - _service.encryptCiphers = function (unencryptedCiphers, key) { - if (!unencryptedCiphers) throw "unencryptedCiphers is undefined or null"; - - var encryptedCiphers = []; - for (var i = 0; i < unencryptedCiphers.length; i++) { - encryptedCiphers.push(_service.encryptCipher(unencryptedCiphers[i], null, key)); - } - - return encryptedCiphers; - }; - - _service.encryptCipher = function (unencryptedCipher, type, key, attachments) { - if (!unencryptedCipher) throw "unencryptedCipher is undefined or null"; - - if (unencryptedCipher.organizationId) { - key = key || cryptoService.getOrgKey(unencryptedCipher.organizationId); - } - - var cipher = { - id: unencryptedCipher.id, - 'type': type || unencryptedCipher.type, - organizationId: unencryptedCipher.organizationId || null, - folderId: unencryptedCipher.folderId === '' ? null : unencryptedCipher.folderId, - favorite: unencryptedCipher.favorite !== null ? unencryptedCipher.favorite : false, - name: cryptoService.encrypt(unencryptedCipher.name, key), - notes: encryptProperty(unencryptedCipher.notes, key), - fields: _service.encryptFields(unencryptedCipher.fields, key) - }; - - var i; - switch (cipher.type) { - case constants.cipherType.login: - var loginData = unencryptedCipher.login; - cipher.login = { - username: encryptProperty(loginData.username, key), - password: encryptProperty(loginData.password, key), - totp: encryptProperty(loginData.totp, key) - }; - if (loginData.uris && loginData.uris.length) { - cipher.login.uris = []; - for (i = 0; i < loginData.uris.length; i++) { - cipher.login.uris.push({ - uri: encryptProperty(loginData.uris[i].uri, key), - match: loginData.uris[i].match - }); - } - } - break; - case constants.cipherType.secureNote: - cipher.secureNote = { - type: unencryptedCipher.secureNote.type - }; - break; - case constants.cipherType.card: - var cardData = unencryptedCipher.card; - cipher.card = { - cardholderName: encryptProperty(cardData.cardholderName, key), - brand: encryptProperty(cardData.brand, key), - number: encryptProperty(cardData.number, key), - expMonth: encryptProperty(cardData.expMonth, key), - expYear: encryptProperty(cardData.expYear, key), - code: encryptProperty(cardData.code, key) - }; - break; - case constants.cipherType.identity: - var identityData = unencryptedCipher.identity; - cipher.identity = { - title: encryptProperty(identityData.title, key), - firstName: encryptProperty(identityData.firstName, key), - middleName: encryptProperty(identityData.middleName, key), - lastName: encryptProperty(identityData.lastName, key), - address1: encryptProperty(identityData.address1, key), - address2: encryptProperty(identityData.address2, key), - address3: encryptProperty(identityData.address3, key), - city: encryptProperty(identityData.city, key), - state: encryptProperty(identityData.state, key), - postalCode: encryptProperty(identityData.postalCode, key), - country: encryptProperty(identityData.country, key), - company: encryptProperty(identityData.company, key), - email: encryptProperty(identityData.email, key), - phone: encryptProperty(identityData.phone, key), - ssn: encryptProperty(identityData.ssn, key), - username: encryptProperty(identityData.username, key), - passportNumber: encryptProperty(identityData.passportNumber, key), - licenseNumber: encryptProperty(identityData.licenseNumber, key) - }; - break; - default: - break; - } - - if (unencryptedCipher.attachments && attachments) { - cipher.attachments = {}; - for (i = 0; i < unencryptedCipher.attachments.length; i++) { - cipher.attachments[unencryptedCipher.attachments[i].id] = - cryptoService.encrypt(unencryptedCipher.attachments[i].fileName, key); - } - } - - return cipher; - }; - - _service.encryptAttachmentFile = function (key, unencryptedFile) { - var deferred = $q.defer(); - - if (unencryptedFile.size > 104857600) { // 100 MB - deferred.reject('Maximum file size is 100 MB.'); - return; - } - - var reader = new FileReader(); - reader.readAsArrayBuffer(unencryptedFile); - reader.onload = function (evt) { - cryptoService.encryptToBytes(evt.target.result, key).then(function (encData) { - deferred.resolve({ - fileName: cryptoService.encrypt(unencryptedFile.name, key), - data: new Uint8Array(encData), - size: unencryptedFile.size - }); - }); - }; - reader.onerror = function (evt) { - deferred.reject('Error reading file.'); - }; - - return deferred.promise; - }; - - _service.encryptFields = function (unencryptedFields, key) { - if (!unencryptedFields || !unencryptedFields.length) { - return null; - } - - var encFields = []; - for (var i = 0; i < unencryptedFields.length; i++) { - if (!unencryptedFields[i]) { - continue; - } - - encFields.push(_service.encryptField(unencryptedFields[i], key)); - } - - return encFields; - }; - - _service.encryptField = function (unencryptedField, key) { - if (!unencryptedField) throw "unencryptedField is undefined or null"; - - return { - type: parseInt(unencryptedField.type), - name: unencryptedField.name ? cryptoService.encrypt(unencryptedField.name, key) : null, - value: unencryptedField.value ? cryptoService.encrypt(unencryptedField.value.toString(), key) : null - }; - }; - - _service.encryptFolders = function (unencryptedFolders, key) { - if (!unencryptedFolders) throw "unencryptedFolders is undefined or null"; - - var encryptedFolders = []; - for (var i = 0; i < unencryptedFolders.length; i++) { - encryptedFolders.push(_service.encryptFolder(unencryptedFolders[i], key)); - } - - return encryptedFolders; - }; - - _service.encryptFolder = function (unencryptedFolder, key) { - if (!unencryptedFolder) throw "unencryptedFolder is undefined or null"; - - return { - id: unencryptedFolder.id, - name: cryptoService.encrypt(unencryptedFolder.name, key) - }; - }; - - _service.encryptCollections = function (unencryptedCollections, orgId) { - if (!unencryptedCollections) throw "unencryptedCollections is undefined or null"; - - var encryptedCollections = []; - for (var i = 0; i < unencryptedCollections.length; i++) { - encryptedCollections.push(_service.encryptCollection(unencryptedCollections[i], orgId)); - } - - return encryptedCollections; - }; - - _service.encryptCollection = function (unencryptedCollection, orgId) { - if (!unencryptedCollection) throw "unencryptedCollection is undefined or null"; - - return { - id: unencryptedCollection.id, - name: cryptoService.encrypt(unencryptedCollection.name, cryptoService.getOrgKey(orgId)) - }; - }; - - function encryptProperty(property, key) { - return !property || property === '' ? null : cryptoService.encrypt(property, key); - } - - return _service; - }); diff --git a/src/app/services/cryptoService.js b/src/app/services/cryptoService.js deleted file mode 100644 index 852394d884..0000000000 --- a/src/app/services/cryptoService.js +++ /dev/null @@ -1,954 +0,0 @@ -angular - .module('bit.services') - - .factory('cryptoService', function ($sessionStorage, constants, $q, $window) { - var _service = {}, - _key, - _encKey, - _legacyEtmKey, - _orgKeys, - _privateKey, - _publicKey, - _crypto = typeof $window.crypto != 'undefined' ? $window.crypto : null, - _subtle = (!!_crypto && typeof $window.crypto.subtle != 'undefined') ? $window.crypto.subtle : null; - - _service.setKey = function (key) { - _key = key; - $sessionStorage.key = _key.keyB64; - }; - - _service.setEncKey = function (encKey, key, alreadyDecrypted) { - if (alreadyDecrypted) { - _encKey = encKey; - $sessionStorage.encKey = _encKey.keyB64; - return; - } - - try { - var encKeyBytes = _service.decrypt(encKey, key, 'raw'); - $sessionStorage.encKey = forge.util.encode64(encKeyBytes); - _encKey = new SymmetricCryptoKey(encKeyBytes); - } - catch (e) { - console.log('Cannot set enc key. Decryption failed.'); - } - }; - - _service.setPrivateKey = function (privateKeyCt, key) { - try { - var privateKeyBytes = _service.decrypt(privateKeyCt, key, 'raw'); - $sessionStorage.privateKey = forge.util.encode64(privateKeyBytes); - _privateKey = forge.pki.privateKeyFromAsn1(forge.asn1.fromDer(privateKeyBytes)); - } - catch (e) { - console.log('Cannot set private key. Decryption failed.'); - } - }; - - _service.setOrgKeys = function (orgKeysCt, privateKey) { - if (!orgKeysCt || Object.keys(orgKeysCt).length === 0) { - return; - } - - _service.clearOrgKeys(); - var orgKeysb64 = {}, - _orgKeys = {}, - setKey = false; - - for (var orgId in orgKeysCt) { - if (orgKeysCt.hasOwnProperty(orgId)) { - try { - var decBytes = _service.rsaDecrypt(orgKeysCt[orgId].key, privateKey); - var decKey = new SymmetricCryptoKey(decBytes); - _orgKeys[orgId] = decKey; - orgKeysb64[orgId] = decKey.keyB64; - setKey = true; - } - catch (e) { - console.log('Cannot set org key for ' + orgId + '. Decryption failed.'); - } - } - } - - if (setKey) { - $sessionStorage.orgKeys = orgKeysb64; - } - else { - _orgKeys = null; - } - }; - - _service.addOrgKey = function (orgId, encOrgKey, privateKey) { - _orgKeys = _service.getOrgKeys(); - if (!_orgKeys) { - _orgKeys = {}; - } - - var orgKeysb64 = $sessionStorage.orgKeys; - if (!orgKeysb64) { - orgKeysb64 = {}; - } - - try { - var decBytes = _service.rsaDecrypt(encOrgKey, privateKey); - var decKey = new SymmetricCryptoKey(decBytes); - _orgKeys[orgId] = decKey; - orgKeysb64[orgId] = decKey.keyB64; - } - catch (e) { - _orgKeys = null; - console.log('Cannot set org key. Decryption failed.'); - } - - $sessionStorage.orgKeys = orgKeysb64; - }; - - _service.getKey = function () { - if (!_key && $sessionStorage.key) { - _key = new SymmetricCryptoKey($sessionStorage.key, true); - } - - if (!_key) { - throw 'key unavailable'; - } - - return _key; - }; - - _service.getEncKey = function () { - if (!_encKey && $sessionStorage.encKey) { - _encKey = new SymmetricCryptoKey($sessionStorage.encKey, true); - } - - return _encKey; - }; - - _service.getPrivateKey = function (outputEncoding) { - outputEncoding = outputEncoding || 'native'; - - if (_privateKey) { - if (outputEncoding === 'raw') { - var privateKeyAsn1 = forge.pki.privateKeyToAsn1(_privateKey); - var privateKeyPkcs8 = forge.pki.wrapRsaPrivateKey(privateKeyAsn1); - return forge.asn1.toDer(privateKeyPkcs8).getBytes(); - } - - return _privateKey; - } - - if ($sessionStorage.privateKey) { - var privateKeyBytes = forge.util.decode64($sessionStorage.privateKey); - _privateKey = forge.pki.privateKeyFromAsn1(forge.asn1.fromDer(privateKeyBytes)); - - if (outputEncoding === 'raw') { - return privateKeyBytes; - } - } - - return _privateKey; - }; - - _service.getPublicKey = function () { - if (_publicKey) { - return _publicKey; - } - - var privateKey = _service.getPrivateKey(); - if (!privateKey) { - return null; - } - - _publicKey = forge.pki.setRsaPublicKey(privateKey.n, privateKey.e); - return _publicKey; - }; - - _service.getOrgKeys = function () { - if (_orgKeys) { - return _orgKeys; - } - - if ($sessionStorage.orgKeys) { - var orgKeys = {}, - setKey = false; - - for (var orgId in $sessionStorage.orgKeys) { - if ($sessionStorage.orgKeys.hasOwnProperty(orgId)) { - orgKeys[orgId] = new SymmetricCryptoKey($sessionStorage.orgKeys[orgId], true); - setKey = true; - } - } - - if (setKey) { - _orgKeys = orgKeys; - } - } - - return _orgKeys; - }; - - _service.getOrgKey = function (orgId) { - var orgKeys = _service.getOrgKeys(); - if (!orgKeys || !(orgId in orgKeys)) { - return null; - } - - return orgKeys[orgId]; - }; - - _service.clearKey = function () { - _key = null; - _legacyEtmKey = null; - delete $sessionStorage.key; - }; - - _service.clearEncKey = function () { - _encKey = null; - delete $sessionStorage.encKey; - }; - - _service.clearKeyPair = function () { - _privateKey = null; - _publicKey = null; - delete $sessionStorage.privateKey; - }; - - _service.clearOrgKeys = function () { - _orgKeys = null; - delete $sessionStorage.orgKeys; - }; - - _service.clearOrgKey = function (orgId) { - if (_orgKeys.hasOwnProperty(orgId)) { - delete _orgKeys[orgId]; - } - - if ($sessionStorage.orgKeys.hasOwnProperty(orgId)) { - delete $sessionStorage.orgKeys[orgId]; - } - }; - - _service.clearKeys = function () { - _service.clearKey(); - _service.clearEncKey(); - _service.clearKeyPair(); - _service.clearOrgKeys(); - }; - - _service.makeKey = function (password, salt) { - if (_subtle != null && !$window.cryptoShimmed && $window.navigator.userAgent.indexOf('Edge') === -1) { - return pbkdf2WC(password, salt, 5000, 256).then(function (keyBuf) { - return new SymmetricCryptoKey(bufToB64(keyBuf), true); - }); - } - else { - var deferred = $q.defer(); - var keyBytes = forge.pbkdf2(forge.util.encodeUtf8(password), forge.util.encodeUtf8(salt), - 5000, 256 / 8, 'sha256'); - deferred.resolve(new SymmetricCryptoKey(keyBytes)); - return deferred.promise; - } - }; - - _service.makeEncKey = function (key) { - var encKey = forge.random.getBytesSync(512 / 8); - var encKeyEnc = _service.encrypt(encKey, key, 'raw'); - return { - encKey: new SymmetricCryptoKey(encKey), - encKeyEnc: encKeyEnc - }; - }; - - _service.makeKeyPair = function (key) { - var deferred = $q.defer(); - - forge.pki.rsa.generateKeyPair({ - bits: 2048, - workers: 2, - workerScript: '/lib/forge/prime.worker.min.js' - }, function (error, keypair) { - if (error) { - deferred.reject(error); - return; - } - - var privateKeyAsn1 = forge.pki.privateKeyToAsn1(keypair.privateKey); - var privateKeyPkcs8 = forge.pki.wrapRsaPrivateKey(privateKeyAsn1); - var privateKeyBytes = forge.asn1.toDer(privateKeyPkcs8).getBytes(); - var privateKeyEncCt = _service.encrypt(privateKeyBytes, key, 'raw'); - - var publicKeyAsn1 = forge.pki.publicKeyToAsn1(keypair.publicKey); - var publicKeyBytes = forge.asn1.toDer(publicKeyAsn1).getBytes(); - - deferred.resolve({ - publicKey: forge.util.encode64(publicKeyBytes), - privateKeyEnc: privateKeyEncCt - }); - }); - - return deferred.promise; - }; - - _service.makeShareKey = function () { - var key = forge.random.getBytesSync(512 / 8); - return { - key: new SymmetricCryptoKey(key), - ct: _service.rsaEncryptMe(key) - }; - }; - - _service.hashPassword = function (password, key) { - if (!key) { - key = _service.getKey(); - } - - if (!password || !key) { - throw 'Invalid parameters.'; - } - - if (_subtle != null && !$window.cryptoShimmed && $window.navigator.userAgent.indexOf('Edge') === -1) { - var keyBuf = key.getBuffers(); - return pbkdf2WC(new Uint8Array(keyBuf.key), password, 1, 256).then(function (hashBuf) { - return bufToB64(hashBuf); - }); - } - else { - var deferred = $q.defer(); - var hashBits = forge.pbkdf2(key.key, forge.util.encodeUtf8(password), 1, 256 / 8, 'sha256'); - deferred.resolve(forge.util.encode64(hashBits)); - return deferred.promise; - } - }; - - function pbkdf2WC(password, salt, iterations, size) { - password = typeof (password) === 'string' ? utf8ToArray(password) : password; - salt = typeof (salt) === 'string' ? utf8ToArray(salt) : salt; - - return _subtle.importKey('raw', password.buffer, { name: 'PBKDF2' }, false, ['deriveKey', 'deriveBits']) - .then(function (importedKey) { - return _subtle.deriveKey( - { name: 'PBKDF2', salt: salt.buffer, iterations: iterations, hash: { name: 'SHA-256' } }, - importedKey, { name: 'AES-CBC', length: size }, true, ['encrypt', 'decrypt']); - }).then(function (derivedKey) { - return _subtle.exportKey('raw', derivedKey); - }); - } - - _service.makeKeyAndHash = function (email, password) { - email = email.toLowerCase(); - var key; - return _service.makeKey(password, email).then(function (theKey) { - key = theKey; - return _service.hashPassword(password, theKey); - }).then(function (theHash) { - return { - key: key, - hash: theHash - }; - }); - }; - - _service.encrypt = function (plainValue, key, plainValueEncoding) { - var encValue = aesEncrypt(plainValue, key, plainValueEncoding); - - var iv = forge.util.encode64(encValue.iv); - var ct = forge.util.encode64(encValue.ct); - var cipherString = iv + '|' + ct; - - if (encValue.mac) { - var mac = forge.util.encode64(encValue.mac); - cipherString = cipherString + '|' + mac; - } - - return encValue.key.encType + '.' + cipherString; - }; - - _service.encryptToBytes = function (plainValue, key) { - return aesEncryptWC(plainValue, key).then(function (encValue) { - var macLen = 0; - if (encValue.mac) { - macLen = encValue.mac.length; - } - - var encBytes = new Uint8Array(1 + encValue.iv.length + macLen + encValue.ct.length); - - encBytes.set([encValue.key.encType]); - encBytes.set(encValue.iv, 1); - if (encValue.mac) { - encBytes.set(encValue.mac, 1 + encValue.iv.length); - } - encBytes.set(encValue.ct, 1 + encValue.iv.length + macLen); - - return encBytes.buffer; - }); - }; - - function aesEncrypt(plainValue, key, plainValueEncoding) { - key = key || _service.getEncKey() || _service.getKey(); - - if (!key) { - throw 'Encryption key unavailable.'; - } - - plainValueEncoding = plainValueEncoding || 'utf8'; - var buffer = forge.util.createBuffer(plainValue, plainValueEncoding); - var ivBytes = forge.random.getBytesSync(16); - var cipher = forge.cipher.createCipher('AES-CBC', key.encKey); - cipher.start({ iv: ivBytes }); - cipher.update(buffer); - cipher.finish(); - - var ctBytes = cipher.output.getBytes(); - - var macBytes = null; - if (key.macKey) { - macBytes = computeMac(ivBytes + ctBytes, key.macKey, false); - } - - return { - iv: ivBytes, - ct: ctBytes, - mac: macBytes, - key: key, - plainValueEncoding: plainValueEncoding - }; - } - - function aesEncryptWC(plainValue, key) { - key = key || _service.getEncKey() || _service.getKey(); - - if (!key) { - throw 'Encryption key unavailable.'; - } - - var obj = { - iv: new Uint8Array(16), - ct: null, - mac: null, - key: key - }; - - var keyBuf = key.getBuffers(); - _crypto.getRandomValues(obj.iv); - - return _subtle.importKey('raw', keyBuf.encKey, { name: 'AES-CBC' }, false, ['encrypt']) - .then(function (encKey) { - return _subtle.encrypt({ name: 'AES-CBC', iv: obj.iv }, encKey, plainValue); - }).then(function (encValue) { - obj.ct = new Uint8Array(encValue); - if (!keyBuf.macKey) { - return null; - } - - var data = new Uint8Array(obj.iv.length + obj.ct.length); - data.set(obj.iv, 0); - data.set(obj.ct, obj.iv.length); - return computeMacWC(data.buffer, keyBuf.macKey); - }).then(function (mac) { - if (mac) { - obj.mac = new Uint8Array(mac); - } - return obj; - }); - } - - _service.rsaEncrypt = function (plainValue, publicKey, key) { - publicKey = publicKey || _service.getPublicKey(); - if (!publicKey) { - throw 'Public key unavailable.'; - } - - if (typeof publicKey === 'string') { - var publicKeyBytes = forge.util.decode64(publicKey); - publicKey = forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyBytes)); - } - - var encryptedBytes = publicKey.encrypt(plainValue, 'RSA-OAEP', { - md: forge.md.sha1.create() - }); - var cipherString = forge.util.encode64(encryptedBytes); - - if (key && key.macKey) { - var mac = computeMac(encryptedBytes, key.macKey, true); - return constants.encType.Rsa2048_OaepSha1_HmacSha256_B64 + '.' + cipherString + '|' + mac; - } - else { - return constants.encType.Rsa2048_OaepSha1_B64 + '.' + cipherString; - } - }; - - _service.rsaEncryptMe = function (plainValue) { - return _service.rsaEncrypt(plainValue, _service.getPublicKey(), _service.getEncKey()); - }; - - _service.decrypt = function (encValue, key, outputEncoding) { - try { - key = key || _service.getEncKey() || _service.getKey(); - - var headerPieces = encValue.split('.'), - encType, - encPieces; - - if (headerPieces.length === 2) { - try { - encType = parseInt(headerPieces[0]); - encPieces = headerPieces[1].split('|'); - } - catch (e) { - console.error('Cannot parse headerPieces.'); - return null; - } - } - else { - encPieces = encValue.split('|'); - encType = encPieces.length === 3 ? constants.encType.AesCbc128_HmacSha256_B64 : - constants.encType.AesCbc256_B64; - } - - if (encType === constants.encType.AesCbc128_HmacSha256_B64 && key.encType === constants.encType.AesCbc256_B64) { - // Old encrypt-then-mac scheme, swap out the key - _legacyEtmKey = _legacyEtmKey || - new SymmetricCryptoKey(key.key, false, constants.encType.AesCbc128_HmacSha256_B64); - key = _legacyEtmKey; - } - - if (encType !== key.encType) { - throw 'encType unavailable.'; - } - - switch (encType) { - case constants.encType.AesCbc128_HmacSha256_B64: - case constants.encType.AesCbc256_HmacSha256_B64: - if (encPieces.length !== 3) { - console.error('Enc type (' + encType + ') not valid.'); - return null; - } - break; - case constants.encType.AesCbc256_B64: - if (encPieces.length !== 2) { - console.error('Enc type (' + encType + ') not valid.'); - return null; - } - break; - default: - console.error('Enc type (' + encType + ') not supported.'); - return null; - } - - var ivBytes = forge.util.decode64(encPieces[0]); - var ctBytes = forge.util.decode64(encPieces[1]); - - if (key.macKey && encPieces.length > 2) { - var macBytes = forge.util.decode64(encPieces[2]); - var computedMacBytes = computeMac(ivBytes + ctBytes, key.macKey, false); - if (!macsEqual(macBytes, computedMacBytes)) { - console.error('MAC failed.'); - return null; - } - } - - var ctBuffer = forge.util.createBuffer(ctBytes); - var decipher = forge.cipher.createDecipher('AES-CBC', key.encKey); - decipher.start({ iv: ivBytes }); - decipher.update(ctBuffer); - decipher.finish(); - - outputEncoding = outputEncoding || 'utf8'; - if (outputEncoding === 'utf8') { - return decipher.output.toString('utf8'); - } - else { - return decipher.output.getBytes(); - } - } - catch (e) { - console.error('Caught unhandled error in decrypt: ' + e); - throw e; - } - }; - - _service.decryptFromBytes = function (encBuf, key) { - try { - if (!encBuf) { - throw 'no encBuf.'; - } - - var encBytes = new Uint8Array(encBuf), - encType = encBytes[0], - ctBytes = null, - ivBytes = null, - macBytes = null; - - switch (encType) { - case constants.encType.AesCbc128_HmacSha256_B64: - case constants.encType.AesCbc256_HmacSha256_B64: - if (encBytes.length <= 49) { // 1 + 16 + 32 + ctLength - console.error('Enc type (' + encType + ') not valid.'); - return null; - } - - ivBytes = slice(encBytes, 1, 17); - macBytes = slice(encBytes, 17, 49); - ctBytes = slice(encBytes, 49); - break; - case constants.encType.AesCbc256_B64: - if (encBytes.length <= 17) { // 1 + 16 + ctLength - console.error('Enc type (' + encType + ') not valid.'); - return null; - } - - ivBytes = slice(encBytes, 1, 17); - ctBytes = slice(encBytes, 17); - break; - default: - console.error('Enc type (' + encType + ') not supported.'); - return null; - } - - return aesDecryptWC( - encType, - ctBytes.buffer, - ivBytes.buffer, - macBytes ? macBytes.buffer : null, - key); - } - catch (e) { - console.error('Caught unhandled error in decryptFromBytes: ' + e); - throw e; - } - }; - - function aesDecryptWC(encType, ctBuf, ivBuf, macBuf, key) { - key = key || _service.getEncKey() || _service.getKey(); - if (!key) { - throw 'Encryption key unavailable.'; - } - - if (key.macKey && !macBuf) { - throw 'macBuf required for this type of key.'; - } - - if (encType !== key.encType) { - throw 'encType unavailable.'; - } - - var keyBuf = key.getBuffers(), - encKey = null; - - return _subtle.importKey('raw', keyBuf.encKey, { name: 'AES-CBC' }, false, ['decrypt']) - .then(function (theEncKey) { - encKey = theEncKey; - - if (!key.macKey || !macBuf) { - return null; - } - - var data = new Uint8Array(ivBuf.byteLength + ctBuf.byteLength); - data.set(new Uint8Array(ivBuf), 0); - data.set(new Uint8Array(ctBuf), ivBuf.byteLength); - return computeMacWC(data.buffer, keyBuf.macKey); - }).then(function (computedMacBuf) { - if (computedMacBuf === null) { - return null; - } - return macsEqualWC(macBuf, computedMacBuf); - }).then(function (macsMatch) { - if (macsMatch === false) { - console.error('MAC failed.'); - return null; - } - return _subtle.decrypt({ name: 'AES-CBC', iv: ivBuf }, encKey, ctBuf); - }); - } - - _service.rsaDecrypt = function (encValue, privateKey, key) { - privateKey = privateKey || _service.getPrivateKey(); - key = key || _service.getEncKey(); - - if (!privateKey) { - throw 'Private key unavailable.'; - } - - var headerPieces = encValue.split('.'), - encType, - encPieces; - - if (headerPieces.length === 1) { - encType = constants.encType.Rsa2048_OaepSha256_B64; - encPieces = [headerPieces[0]]; - } - else if (headerPieces.length === 2) { - try { - encType = parseInt(headerPieces[0]); - encPieces = headerPieces[1].split('|'); - } - catch (e) { - return null; - } - } - - switch (encType) { - case constants.encType.Rsa2048_OaepSha256_B64: - case constants.encType.Rsa2048_OaepSha1_B64: - if (encPieces.length !== 1) { - return null; - } - break; - case constants.encType.Rsa2048_OaepSha256_HmacSha256_B64: - case constants.encType.Rsa2048_OaepSha1_HmacSha256_B64: - if (encPieces.length !== 2) { - return null; - } - break; - default: - return null; - } - - var ctBytes = forge.util.decode64(encPieces[0]); - - if (key && key.macKey && encPieces.length > 1) { - var macBytes = forge.util.decode64(encPieces[1]); - var computedMacBytes = computeMac(ctBytes, key.macKey, false); - if (!macsEqual(macBytes, computedMacBytes)) { - console.error('MAC failed.'); - return null; - } - } - - var md; - if (encType === constants.encType.Rsa2048_OaepSha256_B64 || - encType === constants.encType.Rsa2048_OaepSha256_HmacSha256_B64) { - md = forge.md.sha256.create(); - } - else if (encType === constants.encType.Rsa2048_OaepSha1_B64 || - encType === constants.encType.Rsa2048_OaepSha1_HmacSha256_B64) { - md = forge.md.sha1.create(); - } - else { - throw 'encType unavailable.'; - } - - var decBytes = privateKey.decrypt(ctBytes, 'RSA-OAEP', { - md: md - }); - - return decBytes; - }; - - function computeMac(dataBytes, macKey, b64Output) { - var hmac = forge.hmac.create(); - hmac.start('sha256', macKey); - hmac.update(dataBytes); - var mac = hmac.digest(); - return b64Output ? forge.util.encode64(mac.getBytes()) : mac.getBytes(); - } - - function computeMacWC(dataBuf, macKeyBuf) { - return _subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']) - .then(function (key) { - return _subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, key, dataBuf); - }); - } - - // Safely compare two MACs in a way that protects against timing attacks (Double HMAC Verification). - // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ - // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy - function macsEqual(mac1, mac2) { - var hmac = forge.hmac.create(); - - hmac.start('sha256', getRandomBytes(32)); - hmac.update(mac1); - mac1 = hmac.digest().getBytes(); - - hmac.start(null, null); - hmac.update(mac2); - mac2 = hmac.digest().getBytes(); - - return mac1 === mac2; - } - - function macsEqualWC(mac1Buf, mac2Buf) { - var mac1, - macKey; - - var compareKey = new Uint8Array(32); - _crypto.getRandomValues(compareKey); - - return window.crypto.subtle.importKey('raw', compareKey.buffer, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']) - .then(function (key) { - macKey = key; - return window.crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, macKey, mac1Buf); - }).then(function (mac) { - mac1 = mac; - return window.crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, macKey, mac2Buf); - }).then(function (mac2) { - if (mac1.byteLength !== mac2.byteLength) { - return false; - } - - var arr1 = new Uint8Array(mac1); - var arr2 = new Uint8Array(mac2); - - for (var i = 0; i < arr2.length; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } - - return true; - }); - } - - function SymmetricCryptoKey(keyBytes, b64KeyBytes, encType) { - if (b64KeyBytes) { - keyBytes = forge.util.decode64(keyBytes); - } - - if (!keyBytes) { - throw 'Must provide keyBytes'; - } - - var buffer = forge.util.createBuffer(keyBytes); - if (!buffer || buffer.length() === 0) { - throw 'Couldn\'t make buffer'; - } - var bufferLength = buffer.length(); - - if (encType === null || encType === undefined) { - if (bufferLength === 32) { - encType = constants.encType.AesCbc256_B64; - } - else if (bufferLength === 64) { - encType = constants.encType.AesCbc256_HmacSha256_B64; - } - else { - throw 'Unable to determine encType.'; - } - } - - this.key = keyBytes; - this.keyB64 = forge.util.encode64(keyBytes); - this.encType = encType; - - if (encType === constants.encType.AesCbc256_B64 && bufferLength === 32) { - this.encKey = keyBytes; - this.macKey = null; - } - else if (encType === constants.encType.AesCbc128_HmacSha256_B64 && bufferLength === 32) { - this.encKey = buffer.getBytes(16); // first half - this.macKey = buffer.getBytes(16); // second half - } - else if (encType === constants.encType.AesCbc256_HmacSha256_B64 && bufferLength === 64) { - this.encKey = buffer.getBytes(32); // first half - this.macKey = buffer.getBytes(32); // second half - } - else { - throw 'Unsupported encType/key length.'; - } - } - - SymmetricCryptoKey.prototype.getBuffers = function () { - if (this.keyBuf) { - return this.keyBuf; - } - - var key = b64ToArray(this.keyB64); - - var keys = { - key: key.buffer - }; - - if (this.macKey) { - keys.encKey = slice(key, 0, key.length / 2).buffer; - keys.macKey = slice(key, key.length / 2).buffer; - } - else { - keys.encKey = key.buffer; - keys.macKey = null; - } - - this.keyBuf = keys; - return this.keyBuf; - }; - - function b64ToArray(b64Str) { - var binaryString = $window.atob(b64Str); - var arr = new Uint8Array(binaryString.length); - for (var i = 0; i < binaryString.length; i++) { - arr[i] = binaryString.charCodeAt(i); - } - return arr; - } - - function bufToB64(buf) { - var binary = ''; - var bytes = new Uint8Array(buf); - for (var i = 0; i < bytes.byteLength; i++) { - binary += String.fromCharCode(bytes[i]); - } - return $window.btoa(binary); - } - - function utf8ToArray(str) { - var utf8Str = unescape(encodeURIComponent(str)); - var arr = new Uint8Array(utf8Str.length); - for (var i = 0; i < utf8Str.length; i++) { - arr[i] = utf8Str.charCodeAt(i); - } - return arr; - } - - function slice(arr, begin, end) { - if (arr.slice) { - return arr.slice(begin, end); - } - - // shim for IE - // ref: https://stackoverflow.com/a/21440217 - - arr = arr.buffer; - if (begin === void 0) { - begin = 0; - } - - if (end === void 0) { - end = arr.byteLength; - } - - begin = Math.floor(begin); - end = Math.floor(end); - - if (begin < 0) { - begin += arr.byteLength; - } - - if (end < 0) { - end += arr.byteLength; - } - - begin = Math.min(Math.max(0, begin), arr.byteLength); - end = Math.min(Math.max(0, end), arr.byteLength); - - if (end - begin <= 0) { - return new ArrayBuffer(0); - } - - var result = new ArrayBuffer(end - begin); - var resultBytes = new Uint8Array(result); - var sourceBytes = new Uint8Array(arr, begin, end - begin); - - resultBytes.set(sourceBytes); - return new Uint8Array(result); - } - - function getRandomBytes(byteLength) { - var bytes = new Uint32Array(byteLength / 4); - _crypto.getRandomValues(bytes); - var buffer = forge.util.createBuffer(); - for (var i = 0; i < bytes.length; i++) { - buffer.putInt32(bytes[i]); - } - return buffer.getBytes(); - } - - return _service; - }); \ No newline at end of file diff --git a/src/app/services/event.service.ts b/src/app/services/event.service.ts new file mode 100644 index 0000000000..fade994c68 --- /dev/null +++ b/src/app/services/event.service.ts @@ -0,0 +1,257 @@ +import { Injectable } from '@angular/core'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { DeviceType } from 'jslib/enums/deviceType'; +import { EventType } from 'jslib/enums/eventType'; + +import { EventResponse } from 'jslib/models/response/eventResponse'; + +@Injectable() +export class EventService { + constructor(private i18nService: I18nService) { } + + getDefaultDateFilters() { + const d = new Date(); + const end = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59); + d.setDate(d.getDate() - 30); + const start = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0); + return [this.toDateTimeLocalString(start), this.toDateTimeLocalString(end)]; + } + + formatDateFilters(filterStart: string, filterEnd: string) { + const start: Date = new Date(filterStart); + const end: Date = new Date(filterEnd + ':59.999'); + if (isNaN(start.getTime()) || isNaN(end.getTime()) || end < start) { + throw new Error('Invalid date range.'); + } + return [start.toISOString(), end.toISOString()]; + } + + getEventInfo(ev: EventResponse, options = new EventOptions()): EventInfo { + const appInfo = this.getAppInfo(ev.deviceType); + return { + message: this.getEventMessage(ev, options), + appIcon: appInfo[0], + appName: appInfo[1], + }; + } + + private getEventMessage(ev: EventResponse, options: EventOptions) { + let msg = ''; + switch (ev.type) { + // User + case EventType.User_LoggedIn: + msg = this.i18nService.t('loggedIn'); + break; + case EventType.User_ChangedPassword: + msg = this.i18nService.t('changedPassword'); + break; + case EventType.User_Enabled2fa: + msg = this.i18nService.t('enabled2fa'); + break; + case EventType.User_Disabled2fa: + msg = this.i18nService.t('disabled2fa'); + break; + case EventType.User_Recovered2fa: + msg = this.i18nService.t('recovered2fa'); + break; + case EventType.User_FailedLogIn: + msg = this.i18nService.t('failedLogin'); + break; + case EventType.User_FailedLogIn2fa: + msg = this.i18nService.t('failedLogin2fa'); + break; + // Cipher + case EventType.Cipher_Created: + msg = this.i18nService.t('createdThing', this.i18nService.t('item').toLocaleLowerCase(), + this.formatCipherId(ev, options)); + break; + case EventType.Cipher_Updated: + msg = this.i18nService.t('editedThing', this.i18nService.t('item').toLocaleLowerCase(), + this.formatCipherId(ev, options)); + break; + case EventType.Cipher_Deleted: + msg = this.i18nService.t('deletedThing', this.i18nService.t('item').toLocaleLowerCase(), + this.formatCipherId(ev, options)); + break; + case EventType.Cipher_AttachmentCreated: + msg = this.i18nService.t('createdAttachmentForItem', this.formatCipherId(ev, options)); + break; + case EventType.Cipher_AttachmentDeleted: + msg = this.i18nService.t('deletedAttachmentForItem', this.formatCipherId(ev, options)); + break; + case EventType.Cipher_Shared: + msg = this.i18nService.t('sharedThing', this.i18nService.t('item').toLocaleLowerCase(), + this.formatCipherId(ev, options)); + break; + case EventType.Cipher_UpdatedCollections: + msg = this.i18nService.t('editedCollectionsForItem', this.formatCipherId(ev, options)); + break; + // Collection + case EventType.Collection_Created: + msg = this.i18nService.t('createdThing', this.i18nService.t('collection').toLocaleLowerCase(), + this.formatCollectionId(ev)); + break; + case EventType.Collection_Updated: + msg = this.i18nService.t('editedThing', this.i18nService.t('collection').toLocaleLowerCase(), + this.formatCollectionId(ev)); + break; + case EventType.Collection_Deleted: + msg = this.i18nService.t('deletedThing', this.i18nService.t('collection').toLocaleLowerCase(), + this.formatCollectionId(ev)); + break; + // Group + case EventType.Group_Created: + msg = this.i18nService.t('createdThing', this.i18nService.t('group').toLocaleLowerCase(), + this.formatGroupId(ev)); + break; + case EventType.Group_Updated: + msg = this.i18nService.t('editedThing', this.i18nService.t('group').toLocaleLowerCase(), + this.formatGroupId(ev)); + break; + case EventType.Group_Deleted: + msg = this.i18nService.t('deletedThing', this.i18nService.t('group').toLocaleLowerCase(), + this.formatGroupId(ev)); + break; + // Org user + case EventType.OrganizationUser_Invited: + msg = this.i18nService.t('invitedUser', this.formatOrgUserId(ev)); + break; + case EventType.OrganizationUser_Confirmed: + msg = this.i18nService.t('confirmedUser', this.formatOrgUserId(ev)); + break; + case EventType.OrganizationUser_Updated: + msg = this.i18nService.t('editedThing', this.i18nService.t('user').toLocaleLowerCase(), + this.formatOrgUserId(ev)); + break; + case EventType.OrganizationUser_Removed: + msg = this.i18nService.t('removedThing', this.i18nService.t('user').toLocaleLowerCase(), + this.formatOrgUserId(ev)); + break; + case EventType.OrganizationUser_UpdatedGroups: + msg = this.i18nService.t('editedGroupsForUser', this.formatOrgUserId(ev)); + break; + // Org + case EventType.Organization_Updated: + msg = this.i18nService.t('editedOrgSettings'); + break; + default: + break; + } + return msg === '' ? null : msg; + } + + private getAppInfo(deviceType: DeviceType): [string, string] { + switch (deviceType) { + case DeviceType.Android: + return ['fa-android', this.i18nService.t('mobile') + ' - Android']; + case DeviceType.iOS: + return ['fa-apple', this.i18nService.t('mobile') + ' - iOS']; + case DeviceType.UWP: + return ['fa-windows', this.i18nService.t('mobile') + ' - Windows']; + case DeviceType.ChromeExtension: + return ['fa-chrome', this.i18nService.t('extension') + ' - Chrome']; + case DeviceType.FirefoxExtension: + return ['fa-firefox', this.i18nService.t('extension') + ' - Firefox']; + case DeviceType.OperaExtension: + return ['fa-opera', this.i18nService.t('extension') + ' - Opera']; + case DeviceType.EdgeExtension: + return ['fa-edge', this.i18nService.t('extension') + ' - Edge']; + case DeviceType.VivaldiExtension: + return ['fa-puzzle-piece', this.i18nService.t('extension') + ' - Vivaldi']; + case DeviceType.SafariExtension: + return ['fa-safari', this.i18nService.t('extension') + ' - Safari']; + case DeviceType.WindowsDesktop: + return ['fa-windows', this.i18nService.t('desktop') + ' - Windows']; + case DeviceType.MacOsDesktop: + return ['fa-apple', this.i18nService.t('desktop') + ' - macOS']; + case DeviceType.LinuxDesktop: + return ['fa-linux', this.i18nService.t('desktop') + ' - Linux']; + case DeviceType.ChromeBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - Chrome']; + case DeviceType.FirefoxBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - Firefox']; + case DeviceType.OperaBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - Opera']; + case DeviceType.SafariBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - Safari']; + case DeviceType.VivaldiBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - Vivaldi']; + case DeviceType.EdgeBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - Edge']; + case DeviceType.IEBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - IE']; + case DeviceType.UnknownBrowser: + return ['fa-globe', this.i18nService.t('webVault') + ' - ' + this.i18nService.t('unknown')]; + default: + return ['fa-globe', this.i18nService.t('unknown')]; + } + } + + private formatCipherId(ev: EventResponse, options: EventOptions) { + const shortId = this.getShortId(ev.cipherId); + if (ev.organizationId == null || !options.cipherInfo) { + return '' + shortId + ''; + } + const a = this.makeAnchor(shortId); + a.setAttribute('href', '#/organizations/' + ev.organizationId + '/vault?search=' + shortId + + '&viewEvents=' + ev.cipherId); + return a.outerHTML; + } + + private formatGroupId(ev: EventResponse) { + const shortId = this.getShortId(ev.groupId); + const a = this.makeAnchor(shortId); + a.setAttribute('href', '#/organizations/' + ev.organizationId + '/manage/groups?search=' + shortId); + return a.outerHTML; + } + + private formatCollectionId(ev: EventResponse) { + const shortId = this.getShortId(ev.collectionId); + const a = this.makeAnchor(shortId); + a.setAttribute('href', '#/organizations/' + ev.organizationId + '/manage/collections?search=' + shortId); + return a.outerHTML; + } + + private formatOrgUserId(ev: EventResponse) { + const shortId = this.getShortId(ev.organizationUserId); + const a = this.makeAnchor(shortId); + a.setAttribute('href', '#/organizations/' + ev.organizationId + '/manage/people?search=' + shortId); + return a.outerHTML; + } + + private makeAnchor(shortId: string) { + const a = document.createElement('a'); + a.title = this.i18nService.t('view'); + a.innerHTML = '' + shortId + ''; + return a; + } + + private getShortId(id: string) { + return id.substring(0, 8); + } + + private toDateTimeLocalString(date: Date) { + return date.getFullYear() + + '-' + this.pad(date.getMonth() + 1) + + '-' + this.pad(date.getDate()) + + 'T' + this.pad(date.getHours()) + + ':' + this.pad(date.getMinutes()); + } + + private pad(num: number) { + const norm = Math.floor(Math.abs(num)); + return (norm < 10 ? '0' : '') + norm; + } +} + +export class EventInfo { + message: string; + appIcon: string; + appName: string; +} + +export class EventOptions { + cipherInfo = true; +} diff --git a/src/app/services/eventService.js b/src/app/services/eventService.js deleted file mode 100644 index ce80468092..0000000000 --- a/src/app/services/eventService.js +++ /dev/null @@ -1,269 +0,0 @@ -angular - .module('bit.services') - - .factory('eventService', function (constants, $filter) { - var _service = {}; - - _service.getDefaultDateFilters = function () { - var d = new Date(); - var filterEnd = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59); - d.setDate(d.getDate() - 30); - var filterStart = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0); - - return { - start: filterStart, - end: filterEnd - }; - }; - - _service.formatDateFilters = function (filterStart, filterEnd) { - var result = { - start: null, - end: null, - error: null - }; - - try { - var format = 'yyyy-MM-ddTHH:mm'; - result.start = $filter('date')(filterStart, format + 'Z', 'UTC'); - result.end = $filter('date')(filterEnd, format + ':59.999Z', 'UTC'); - } catch (e) { } - - if (!result.start || !result.end || result.end < result.start) { - result.error = 'Invalid date range.'; - } - - return result; - }; - - _service.getEventInfo = function (ev, options) { - options = options || { - cipherInfo: true - }; - - var appInfo = getAppInfo(ev); - - return { - message: getEventMessage(ev, options), - appIcon: appInfo.icon, - appName: appInfo.name - }; - }; - - function getEventMessage(ev, options) { - var msg = ''; - switch (ev.Type) { - // User - case constants.eventType.User_LoggedIn: - msg = 'Logged in.'; - break; - case constants.eventType.User_ChangedPassword: - msg = 'Changed account password.'; - break; - case constants.eventType.User_Enabled2fa: - msg = 'Enabled two-step login.'; - break; - case constants.eventType.User_Disabled2fa: - msg = 'Disabled two-step login.'; - break; - case constants.eventType.User_Recovered2fa: - msg = 'Recovered account from two-step login.'; - break; - case constants.eventType.User_FailedLogIn: - msg = 'Login attempt failed with incorrect password.'; - break; - case constants.eventType.User_FailedLogIn2fa: - msg = 'Login attempt failed with incorrect two-step login.'; - break; - // Cipher - case constants.eventType.Cipher_Created: - msg = options.cipherInfo ? 'Created item ' + formatCipherId(ev) + '.' : 'Created.'; - break; - case constants.eventType.Cipher_Updated: - msg = options.cipherInfo ? 'Edited item ' + formatCipherId(ev) + '.' : 'Edited.'; - break; - case constants.eventType.Cipher_Deleted: - msg = options.cipherInfo ? 'Deleted item ' + formatCipherId(ev) + '.' : 'Deleted'; - break; - case constants.eventType.Cipher_AttachmentCreated: - msg = options.cipherInfo ? 'Created attachment for item ' + formatCipherId(ev) + '.' : - 'Created attachment.'; - break; - case constants.eventType.Cipher_AttachmentDeleted: - msg = options.cipherInfo ? 'Deleted attachment for item ' + formatCipherId(ev) + '.' : - 'Deleted attachment.'; - break; - case constants.eventType.Cipher_Shared: - msg = options.cipherInfo ? 'Shared item ' + formatCipherId(ev) + '.' : 'Shared.'; - break; - case constants.eventType.Cipher_UpdatedCollections: - msg = options.cipherInfo ? 'Update collections for item ' + formatCipherId(ev) + '.' : - 'Updated collections.'; - break; - // Collection - case constants.eventType.Collection_Created: - msg = 'Created collection ' + formatCollectionId(ev) + '.'; - break; - case constants.eventType.Collection_Updated: - msg = 'Edited collection ' + formatCollectionId(ev) + '.'; - break; - case constants.eventType.Collection_Deleted: - msg = 'Deleted collection ' + formatCollectionId(ev) + '.'; - break; - // Group - case constants.eventType.Group_Created: - msg = 'Created group ' + formatGroupId(ev) + '.'; - break; - case constants.eventType.Group_Updated: - msg = 'Edited group ' + formatGroupId(ev) + '.'; - break; - case constants.eventType.Group_Deleted: - msg = 'Deleted group ' + formatGroupId(ev) + '.'; - break; - // Org user - case constants.eventType.OrganizationUser_Invited: - msg = 'Invited user ' + formatOrgUserId(ev) + '.'; - break; - case constants.eventType.OrganizationUser_Confirmed: - msg = 'Confirmed user ' + formatOrgUserId(ev) + '.'; - break; - case constants.eventType.OrganizationUser_Updated: - msg = 'Edited user ' + formatOrgUserId(ev) + '.'; - break; - case constants.eventType.OrganizationUser_Removed: - msg = 'Removed user ' + formatOrgUserId(ev) + '.'; - break; - case constants.eventType.OrganizationUser_UpdatedGroups: - msg = 'Edited groups for user ' + formatOrgUserId(ev) + '.'; - break; - // Org - case constants.eventType.Organization_Updated: - msg = 'Edited organization settings.'; - break; - default: - break; - } - - return msg === '' ? null : msg; - } - - function getAppInfo(ev) { - var appInfo = { - icon: 'fa-globe', - name: 'Unknown' - }; - - switch (ev.DeviceType) { - case constants.deviceType.android: - appInfo.icon = 'fa-android'; - appInfo.name = 'Mobile App - Android'; - break; - case constants.deviceType.ios: - appInfo.icon = 'fa-apple'; - appInfo.name = 'Mobile App - iOS'; - break; - case constants.deviceType.uwp: - appInfo.icon = 'fa-windows'; - appInfo.name = 'Mobile App - Windows'; - break; - case constants.deviceType.chromeExt: - appInfo.icon = 'fa-chrome'; - appInfo.name = 'Extension - Chrome'; - break; - case constants.deviceType.firefoxExt: - appInfo.icon = 'fa-firefox'; - appInfo.name = 'Extension - Firefox'; - break; - case constants.deviceType.operaExt: - appInfo.icon = 'fa-opera'; - appInfo.name = 'Extension - Opera'; - break; - case constants.deviceType.edgeExt: - appInfo.icon = 'fa-edge'; - appInfo.name = 'Extension - Edge'; - break; - case constants.deviceType.vivaldiExt: - appInfo.icon = 'fa-puzzle-piece'; - appInfo.name = 'Extension - Vivaldi'; - break; - case constants.deviceType.windowsDesktop: - appInfo.icon = 'fa-windows'; - appInfo.name = 'Desktop - Windows'; - break; - case constants.deviceType.macOsDesktop: - appInfo.icon = 'fa-apple'; - appInfo.name = 'Desktop - macOS'; - break; - case constants.deviceType.linuxDesktop: - appInfo.icon = 'fa-linux'; - appInfo.name = 'Desktop - Linux'; - break; - case constants.deviceType.chrome: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Chrome'; - break; - case constants.deviceType.firefox: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Firefox'; - break; - case constants.deviceType.opera: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Opera'; - break; - case constants.deviceType.safari: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Safari'; - break; - case constants.deviceType.vivaldi: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Vivaldi'; - break; - case constants.deviceType.edge: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Edge'; - break; - case constants.deviceType.ie: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - IE'; - break; - case constants.deviceType.unknown: - appInfo.icon = 'fa-globe'; - appInfo.name = 'Web Vault - Unknown'; - break; - default: - break; - } - - return appInfo; - } - - function formatCipherId(ev) { - var shortId = ev.CipherId.substring(0, 8); - if (!ev.OrganizationId) { - return '' + shortId + ''; - } - - return '' + - '' + shortId + ''; - } - - function formatGroupId(ev) { - var shortId = ev.GroupId.substring(0, 8); - return '' + - '' + shortId + ''; - } - - function formatCollectionId(ev) { - var shortId = ev.CollectionId.substring(0, 8); - return '' + - '' + shortId + ''; - } - - function formatOrgUserId(ev) { - var shortId = ev.OrganizationUserId.substring(0, 8); - return '' + - '' + shortId + ''; - } - - return _service; - }); diff --git a/src/app/services/importService.js b/src/app/services/importService.js deleted file mode 100644 index d82f9ac438..0000000000 --- a/src/app/services/importService.js +++ /dev/null @@ -1,3184 +0,0 @@ -angular - .module('bit.services') - - .factory('importService', function (constants) { - var _service = {}; - - _service.import = function (source, file, success, error) { - if (!file) { - error(); - return; - } - - switch (source) { - case 'bitwardencsv': - importBitwardenCsv(file, success, error); - break; - case 'lastpass': - importLastPass(file, success, error, false); - break; - case 'safeincloudxml': - importSafeInCloudXml(file, success, error); - break; - case 'keepass2xml': - importKeePass2Xml(file, success, error); - break; - case 'keepassxcsv': - importKeePassXCsv(file, success, error); - break; - case 'padlockcsv': - importPadlockCsv(file, success, error); - break; - case '1password1pif': - import1Password1Pif(file, success, error); - break; - case '1password6wincsv': - import1Password6WinCsv(file, success, error); - break; - case 'chromecsv': - case 'vivaldicsv': - case 'operacsv': - importChromeCsv(file, success, error); - break; - case 'firefoxpasswordexportercsv': - importFirefoxPasswordExporterCsv(file, success, error); - break; - case 'upmcsv': - importUpmCsv(file, success, error); - break; - case 'keepercsv': - importKeeperCsv(file, success, error); - break; - case 'passworddragonxml': - importPasswordDragonXml(file, success, error); - break; - case 'enpasscsv': - importEnpassCsv(file, success, error); - break; - case 'pwsafexml': - importPasswordSafeXml(file, success, error); - break; - case 'dashlanecsv': - importDashlaneCsv(file, success, error); - break; - case 'stickypasswordxml': - importStickyPasswordXml(file, success, error); - break; - case 'msecurecsv': - importmSecureCsv(file, success, error); - break; - case 'truekeycsv': - importTrueKeyCsv(file, success, error); - break; - case 'clipperzhtml': - importClipperzHtml(file, success, error); - break; - case 'avirajson': - importAviraJson(file, success, error); - break; - case 'roboformhtml': - importRoboFormHtml(file, success, error); - break; - case 'saferpasscsv': - importSaferPassCsv(file, success, error); - break; - case 'ascendocsv': - importAscendoCsv(file, success, error); - break; - case 'passwordbossjson': - importPasswordBossJson(file, success, error); - break; - case 'zohovaultcsv': - importZohoVaultCsv(file, success, error); - break; - case 'splashidcsv': - importSplashIdCsv(file, success, error); - break; - case 'meldiumcsv': - importMeldiumCsv(file, success, error); - break; - case 'passkeepcsv': - importPassKeepCsv(file, success, error); - break; - case 'gnomejson': - importGnomeJson(file, success, error); - break; - default: - error(); - break; - } - }; - - _service.importOrg = function (source, file, success, error) { - if (!file) { - error(); - return; - } - - switch (source) { - case 'bitwardencsv': - importBitwardenOrgCsv(file, success, error); - break; - case 'lastpass': - importLastPass(file, success, error, true); - break; - default: - error(); - break; - } - }; - - // helpers - - var _passwordFieldNames = [ - 'password', 'pass word', 'passphrase', 'pass phrase', - 'pass', 'code', 'code word', 'codeword', - 'secret', 'secret word', 'personpwd', - 'key', 'keyword', 'key word', 'keyphrase', 'key phrase', - 'form_pw', 'wppassword', 'pin', 'pwd', 'pw', 'pword', 'passwd', - 'p', 'serial', 'serial#', 'license key', 'reg #', - - // Non-English names - 'passwort' - ]; - - var _usernameFieldNames = [ - 'user', 'name', 'user name', 'username', 'login name', - 'email', 'e-mail', 'id', 'userid', 'user id', - 'login', 'form_loginname', 'wpname', 'mail', - 'loginid', 'login id', 'log', 'personlogin', - 'first name', 'last name', 'card#', 'account #', - 'member', 'member #', - - // Non-English names - 'nom', 'benutzername' - ]; - - var _notesFieldNames = [ - "note", "notes", "comment", "comments", "memo", - "description", "free form", "freeform", - "free text", "freetext", "free", - - // Non-English names - "kommentar" - ]; - - var _uriFieldNames = [ - 'url', 'hyper link', 'hyperlink', 'link', - 'host', 'hostname', 'host name', 'server', 'address', - 'hyper ref', 'href', 'web', 'website', 'web site', 'site', - 'web-site', 'uri', - - // Non-English names - 'ort', 'adresse' - ]; - - function loginNameFromUrl(url) { - var a = document.createElement('a'); - a.href = url; - return a.hostname.startsWith('www.') ? a.hostname.replace('www.', '') : a.hostname; - } - - function isField(fieldText, refFieldValues) { - if (!fieldText || fieldText === '') { - return false; - } - - fieldText = fieldText.trim().toLowerCase(); - - for (var i = 0; i < refFieldValues.length; i++) { - if (fieldText === refFieldValues[i]) { - return true; - } - } - - return false; - } - - function fixUri(uri) { - uri = uri.toLowerCase().trim(); - if (uri.indexOf('://') === -1 && uri.indexOf('.') >= 0) { - uri = 'http://' + uri; - } - - if (uri.length > 1000) { - return uri.substring(0, 1000); - } - - return uri; - } - - function makeUriArray(uri) { - if (!uri) { - return null; - } - - if (typeof uri === 'string') { - return [{ - uri: fixUri(uri), - match: null - }]; - } - - if (uri.length) { - var returnArr = []; - for (var i = 0; i < uri.length; i++) { - returnArr.push({ - uri: fixUri(uri[i]), - match: null - }); - } - return returnArr; - } - - return null; - } - - function parseSingleRowCsv(rowData) { - if (!rowData || rowData === '') { - return null; - } - var parsedRow = Papa.parse(rowData); - if (parsedRow && parsedRow.data && parsedRow.data.length && parsedRow.data[0].length) { - return parsedRow.data[0]; - } - return null; - } - - function parseCsvErrors(results) { - if (results.errors && results.errors.length) { - for (var i = 0; i < results.errors.length; i++) { - console.warn('Error parsing row ' + results.errors[i].row + ': ' + results.errors[i].message); - } - } - } - - function getFileContents(file, contentsCallback, errorCallback) { - if (typeof file === 'string') { - contentsCallback(file); - } - else { - var reader = new FileReader(); - reader.readAsText(file, 'utf-8'); - reader.onload = function (evt) { - contentsCallback(evt.target.result); - }; - reader.onerror = function (evt) { - errorCallback(); - }; - } - } - - function getXmlFileContents(file, xmlCallback, errorCallback) { - getFileContents(file, function (fileContents) { - xmlCallback($.parseXML(fileContents)); - }, errorCallback); - } - - // ref https://stackoverflow.com/a/5911300 - function getCardType(number) { - if (!number) { - return null; - } - - // Visa - var re = new RegExp('^4'); - if (number.match(re) != null) { - return 'Visa'; - } - - // Mastercard - // Updated for Mastercard 2017 BINs expansion - if (/^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$/.test(number)) { - return 'Mastercard'; - } - - // AMEX - re = new RegExp('^3[47]'); - if (number.match(re) != null) { - return 'Amex'; - } - - // Discover - re = new RegExp('^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)'); - if (number.match(re) != null) { - return 'Discover'; - } - - // Diners - re = new RegExp('^36'); - if (number.match(re) != null) { - return 'Diners Club'; - } - - // Diners - Carte Blanche - re = new RegExp('^30[0-5]'); - if (number.match(re) != null) { - return 'Diners Club'; - } - - // JCB - re = new RegExp('^35(2[89]|[3-8][0-9])'); - if (number.match(re) != null) { - return 'JCB'; - } - - // Visa Electron - re = new RegExp('^(4026|417500|4508|4844|491(3|7))'); - if (number.match(re) != null) { - return 'Visa'; - } - - return null; - } - - // importers - - function importBitwardenCsv(file, success, error) { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = [], - i = 0; - - angular.forEach(results.data, function (value, key) { - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = value.folder && value.folder !== '', - addFolder = hasFolder; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === value.folder) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher = { - favorite: value.favorite && value.favorite !== '' && value.favorite !== '0' ? true : false, - notes: value.notes && value.notes !== '' ? value.notes : null, - name: value.name && value.name !== '' ? value.name : '--', - type: constants.cipherType.login - }; - - if (value.fields && value.fields !== '') { - var fields = value.fields.split(/(?:\r\n|\r|\n)/); - for (i = 0; i < fields.length; i++) { - if (!fields[i] || fields[i] === '') { - continue; - } - - var delimPosition = fields[i].lastIndexOf(': '); - if (delimPosition === -1) { - continue; - } - - if (!cipher.fields) { - cipher.fields = []; - } - - var field = { - name: fields[i].substr(0, delimPosition), - value: null, - type: constants.fieldType.text - }; - - if (fields[i].length > (delimPosition + 2)) { - field.value = fields[i].substr(delimPosition + 2); - } - - cipher.fields.push(field); - } - } - - var valueType = value.type ? value.type.toLowerCase() : null; - switch (valueType) { - case 'login': - case null: - case undefined: - cipher.type = constants.cipherType.login; - - var totp = value.login_totp || value.totp; - var uris = parseSingleRowCsv(value.login_uri || value.uri); - var username = value.login_username || value.username; - var password = value.login_password || value.password; - cipher.login = { - totp: totp && totp !== '' ? totp : null, - uris: makeUriArray(uris), - username: username && username !== '' ? username : null, - password: password && password !== '' ? password : null - }; - break; - case 'note': - cipher.type = constants.cipherType.secureNote; - cipher.secureNote = { - type: 0 // generic note - }; - break; - default: - break; - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: value.folder - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - }); - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importBitwardenOrgCsv(file, success, error) { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var collections = [], - ciphers = [], - collectionRelationships = [], - i; - - angular.forEach(results.data, function (value, key) { - var cipherIndex = ciphers.length; - - if (value.collections && value.collections !== '') { - var cipherCollections = value.collections.split(','); - - for (i = 0; i < cipherCollections.length; i++) { - var addCollection = true; - var collectionIndex = collections.length; - - for (var j = 0; j < collections.length; j++) { - if (collections[j].name === cipherCollections[i]) { - addCollection = false; - collectionIndex = j; - break; - } - } - - if (addCollection) { - collections.push({ - name: cipherCollections[i] - }); - } - - collectionRelationships.push({ - key: cipherIndex, - value: collectionIndex - }); - } - } - - var cipher = { - favorite: false, - notes: value.notes && value.notes !== '' ? value.notes : null, - name: value.name && value.name !== '' ? value.name : '--', - type: constants.cipherType.login - }; - - if (value.fields && value.fields !== '') { - var fields = value.fields.split(/(?:\r\n|\r|\n)/); - for (i = 0; i < fields.length; i++) { - if (!fields[i] || fields[i] === '') { - continue; - } - - var delimPosition = fields[i].lastIndexOf(': '); - if (delimPosition === -1) { - continue; - } - - if (!cipher.fields) { - cipher.fields = []; - } - - var field = { - name: fields[i].substr(0, delimPosition), - value: null, - type: constants.fieldType.text - }; - - if (fields[i].length > (delimPosition + 2)) { - field.value = fields[i].substr(delimPosition + 2); - } - - cipher.fields.push(field); - } - } - - var valueType = value.type ? value.type.toLowerCase() : null; - switch (valueType) { - case 'login': - case null: - case undefined: - cipher.type = constants.cipherType.login; - - var totp = value.login_totp || value.totp; - var uris = parseSingleRowCsv(value.login_uri || value.uri); - var username = value.login_username || value.username; - var password = value.login_password || value.password; - cipher.login = { - totp: totp && totp !== '' ? totp : null, - uris: makeUriArray(uris), - username: username && username !== '' ? username : null, - password: password && password !== '' ? password : null - }; - break; - case 'note': - cipher.type = constants.cipherType.secureNote; - cipher.secureNote = { - type: 0 // generic note - }; - break; - default: - break; - } - - ciphers.push(cipher); - }); - - success(collections, ciphers, collectionRelationships); - } - }); - } - - function importLastPass(file, success, error, org) { - if (typeof file !== 'string' && file.type && file.type === 'text/html') { - var reader = new FileReader(); - reader.readAsText(file, 'utf-8'); - reader.onload = function (evt) { - var doc = $(evt.target.result); - var pre = doc.find('pre'); - var csv, results; - - if (pre.length === 1) { - csv = pre.text().trim(); - results = Papa.parse(csv, { - header: true, - encoding: 'UTF-8' - }); - parseData(results.data); - } - else { - var foundPre = false; - for (var i = 0; i < doc.length; i++) { - if (doc[i].tagName.toLowerCase() === 'pre') { - foundPre = true; - csv = doc[i].outerText.trim(); - results = Papa.parse(csv, { - header: true, - encoding: 'UTF-8' - }); - parseData(results.data); - break; - } - } - - if (!foundPre) { - error(); - } - } - }; - - reader.onerror = function (evt) { - error(); - }; - } - else { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - parseData(results.data); - }, - beforeFirstChunk: function (chunk) { - return chunk.replace(/^\s+/, ''); - } - }); - } - - function parseSecureNoteMapping(extraParts, map, skip) { - var obj = { - dataObj: {}, - notes: null - }; - for (var i = 0; i < extraParts.length; i++) { - var fieldParts = extraParts[i].split(':'); - if (fieldParts.length < 1 || fieldParts[0] === 'NoteType' || skip.indexOf(fieldParts[0]) > -1 || - !fieldParts[1] || fieldParts[1] === '') { - continue; - } - - if (fieldParts[0] === 'Notes') { - if (obj.notes) { - obj.notes += ('\n' + fieldParts[1]); - } - else { - obj.notes = fieldParts[1]; - } - } - else if (map.hasOwnProperty(fieldParts[0])) { - obj.dataObj[map[fieldParts[0]]] = fieldParts[1]; - } - else { - if (obj.notes) { - obj.notes += '\n'; - } - else { - obj.notes = ''; - } - - obj.notes += (fieldParts[0] + ': ' + fieldParts[1]); - } - } - - return obj; - } - - function parseCard(value) { - var cardData = { - cardholderName: value.ccname && value.ccname !== '' ? value.ccname : null, - number: value.ccnum && value.ccnum !== '' ? value.ccnum : null, - brand: value.ccnum && value.ccnum !== '' ? getCardType(value.ccnum) : null, - code: value.cccsc && value.cccsc !== '' ? value.cccsc : null - }; - - if (value.ccexp && value.ccexp !== '' && value.ccexp.indexOf('-') > -1) { - var ccexpParts = value.ccexp.split('-'); - if (ccexpParts.length > 1) { - cardData.expYear = ccexpParts[0]; - cardData.expMonth = ccexpParts[1]; - if (cardData.expMonth.length === 2 && cardData.expMonth[0] === '0') { - cardData.expMonth = cardData.expMonth[1]; - } - } - } - - return cardData; - } - - function parseData(data) { - var folders = [], - ciphers = [], - cipherRelationships = [], - i = 0; - - angular.forEach(data, function (value, key) { - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = value.grouping && value.grouping !== '' && value.grouping !== '(none)', - addFolder = hasFolder; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === value.grouping) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher; - if (value.hasOwnProperty('profilename') && value.hasOwnProperty('profilelanguage')) { - // form fill - cipher = { - favorite: false, - name: value.profilename && value.profilename !== '' ? value.profilename : '--', - type: constants.cipherType.card - }; - - if (value.title !== '' || value.firstname !== '' || value.lastname !== '' || - value.address1 !== '' || value.phone !== '' || value.username !== '' || - value.email !== '') { - cipher.type = constants.cipherType.identity; - } - } - else { - // site or secure note - cipher = { - favorite: org ? false : value.fav === '1', - name: value.name && value.name !== '' ? value.name : '--', - type: value.url === 'http://sn' ? constants.cipherType.secureNote : constants.cipherType.login - }; - } - - if (cipher.type === constants.cipherType.login) { - cipher.login = { - uris: makeUriArray(value.url), - username: value.username && value.username !== '' ? value.username : null, - password: value.password && value.password !== '' ? value.password : null - }; - - cipher.notes = value.extra && value.extra !== '' ? value.extra : null; - } - else if (cipher.type === constants.cipherType.secureNote) { - var extraParts = value.extra.split(/(?:\r\n|\r|\n)/), - processedNote = false; - if (extraParts.length) { - var typeParts = extraParts[0].split(':'); - if (typeParts.length > 1 && typeParts[0] === 'NoteType' && - (typeParts[1] === 'Credit Card' || typeParts[1] === 'Address')) { - var mappedData = null; - if (typeParts[1] === 'Credit Card') { - mappedData = parseSecureNoteMapping(extraParts, { - 'Number': 'number', - 'Name on Card': 'cardholderName', - 'Security Code': 'code' - }, []); - cipher.type = constants.cipherType.card; - cipher.card = mappedData.dataObj; - } - else if (typeParts[1] === 'Address') { - mappedData = parseSecureNoteMapping(extraParts, { - 'Title': 'title', - 'First Name': 'firstName', - 'Last Name': 'lastName', - 'Middle Name': 'middleName', - 'Company': 'company', - 'Address 1': 'address1', - 'Address 2': 'address2', - 'Address 3': 'address3', - 'City / Town': 'city', - 'State': 'state', - 'Zip / Postal Code': 'postalCode', - 'Country': 'country', - 'Email Address': 'email', - 'Username': 'username' - }, []); - cipher.type = constants.cipherType.identity; - cipher.identity = mappedData.dataObj; - } - - processedNote = true; - cipher.notes = mappedData.notes; - } - } - - if (!processedNote) { - cipher.secureNote = { - type: 0 - }; - cipher.notes = value.extra && value.extra !== '' ? value.extra : null; - } - } - else if (cipher.type === constants.cipherType.card) { - cipher.card = parseCard(value); - cipher.notes = value.notes && value.notes !== '' ? value.notes : null; - } - else if (cipher.type === constants.cipherType.identity) { - cipher.identity = { - title: value.title && value.title !== '' ? value.title : null, - firstName: value.firstname && value.firstname !== '' ? value.firstname : null, - middleName: value.middlename && value.middlename !== '' ? value.middlename : null, - lastName: value.lastname && value.lastname !== '' ? value.lastname : null, - username: value.username && value.username !== '' ? value.username : null, - company: value.company && value.company !== '' ? value.company : null, - ssn: value.ssn && value.ssn !== '' ? value.ssn : null, - address1: value.address1 && value.address1 !== '' ? value.address1 : null, - address2: value.address2 && value.address2 !== '' ? value.address2 : null, - address3: value.address3 && value.address3 !== '' ? value.address3 : null, - city: value.city && value.city !== '' ? value.city : null, - state: value.state && value.state !== '' ? value.state : null, - postalCode: value.zip && value.zip !== '' ? value.zip : null, - country: value.country && value.country !== '' ? value.country : null, - email: value.email && value.email !== '' ? value.email : null, - phone: value.phone && value.phone !== '' ? value.phone : null - }; - - cipher.notes = value.notes && value.notes !== '' ? value.notes : null; - - if (cipher.identity.title) { - cipher.identity.title = cipher.identity.title.charAt(0).toUpperCase() + - cipher.identity.title.slice(1); - } - - if (value.ccnum && value.ccnum !== '') { - // there is a card on this identity too - var cardCipher = JSON.parse(JSON.stringify(cipher)); // cloned - cardCipher.identity = null; - cardCipher.type = constants.cipherType.card; - cardCipher.card = parseCard(value); - ciphers.push(cardCipher); - } - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: value.grouping - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - cipherRelationships.push(relationship); - } - }); - - success(folders, ciphers, cipherRelationships); - } - } - - function importSafeInCloudXml(file, success, error) { - var folders = [], - ciphers = [], - cipherRelationships = [], - foldersIndex = [], - i = 0, - j = 0; - - getXmlFileContents(file, parse, error); - - function parse(xmlDoc) { - var xml = $(xmlDoc); - - var db = xml.find('database'); - if (db.length) { - var labels = db.find('> label'); - if (labels.length) { - for (i = 0; i < labels.length; i++) { - var label = $(labels[i]); - foldersIndex[label.attr('id')] = folders.length; - folders.push({ - name: label.attr('name') - }); - } - } - - var cards = db.find('> card'); - if (cards.length) { - for (i = 0; i < cards.length; i++) { - var card = $(cards[i]); - if (card.attr('template') === 'true') { - continue; - } - - var cipher = { - favorite: false, - notes: '', - name: card.attr('title'), - fields: null - }; - - if (!cipher.name || cipher.name === '') { - cipher.name = '--'; - } - - if (card.attr('type') === 'note') { - cipher.type = constants.cipherType.secureNote; - cipher.secureNote = { - type: 0 // generic note - }; - } - else { - cipher.type = constants.cipherType.login; - cipher.login = {}; - - var fields = card.find('> field'); - for (j = 0; j < fields.length; j++) { - var field = $(fields[j]); - - var text = field.text(); - var type = field.attr('type'); - var name = field.attr('name'); - - if (text && text !== '') { - if (type === 'login') { - cipher.login.username = text; - } - else if (type === 'password') { - cipher.login.password = text; - } - else if (type === 'notes') { - cipher.notes += (text + '\n'); - } - else if (type === 'weblogin' || type === 'website') { - cipher.login.uris = makeUriArray(text); - } - else if (text.length > 200) { - cipher.notes += (name + ': ' + text + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - cipher.fields.push({ - name: name, - value: text, - type: constants.fieldType.text - }); - } - } - } - } - - var notes = card.find('> notes'); - for (j = 0; j < notes.length; j++) { - cipher.notes += ($(notes[j]).text() + '\n'); - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - - labels = card.find('> label_id'); - if (labels.length) { - var labelId = $(labels[0]).text(); - var folderIndex = foldersIndex[labelId]; - if (labelId !== null && labelId !== '' && folderIndex !== null) { - cipherRelationships.push({ - key: ciphers.length - 1, - value: folderIndex - }); - } - } - } - } - - success(folders, ciphers, cipherRelationships); - } - else { - error(); - } - } - } - - function importPadlockCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - var customFieldHeaders = []; - - // CSV index ref: 0 = name, 1 = category, 2 = username, 3 = password, 4+ = custom fields - - var i = 0, - j = 0; - - for (i = 0; i < results.data.length; i++) { - var value = results.data[i]; - if (i === 0) { - // header row - for (j = 4; j < value.length; j++) { - customFieldHeaders.push(value[j]); - } - - continue; - } - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = value[1] && value[1] !== '', - addFolder = hasFolder; - - if (hasFolder) { - for (j = 0; j < folders.length; j++) { - if (folders[j].name === value[1]) { - addFolder = false; - folderIndex = j; - break; - } - } - } - - var cipher = { - favorite: false, - type: constants.cipherType.login, - notes: null, - name: value[0] && value[0] !== '' ? value[0] : '--', - login: { - uris: null, - username: value[2] && value[2] !== '' ? value[2] : null, - password: value[3] && value[3] !== '' ? value[3] : null - }, - fields: null - }; - - if (customFieldHeaders.length) { - for (j = 4; j < value.length; j++) { - var cf = value[j]; - if (!cf || cf === '') { - continue; - } - - var cfHeader = customFieldHeaders[j - 4]; - if (cfHeader.toLowerCase() === 'url' || cfHeader.toLowerCase() === 'uri') { - cipher.login.uris = makeUriArray(cf); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: cfHeader, - value: cf, - type: constants.fieldType.text - }); - } - } - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: value[1] - }); - } - - if (hasFolder) { - folderRelationships.push({ - key: cipherIndex, - value: folderIndex - }); - } - } - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importKeePass2Xml(file, success, error) { - var folders = [], - ciphers = [], - folderRelationships = []; - - getXmlFileContents(file, parse, error); - - function parse(xmlDoc) { - var xml = $(xmlDoc); - - var root = xml.find('Root'); - if (root.length) { - var group = root.find('> Group'); - if (group.length) { - traverse($(group[0]), true, ''); - success(folders, ciphers, folderRelationships); - } - } - else { - error(); - } - } - - function traverse(node, isRootNode, groupNamePrefix) { - var nodeEntries = []; - var folderIndex = folders.length; - var groupName = groupNamePrefix; - - if (!isRootNode) { - if (groupName !== '') { - groupName += ' > '; - } - groupName += node.find('> Name').text(); - folders.push({ - name: groupName - }); - } - - var entries = node.find('> Entry'); - if (entries.length) { - for (var i = 0; i < entries.length; i++) { - var entry = $(entries[i]); - var cipherIndex = ciphers.length; - var cipher = { - favorite: false, - notes: null, - name: null, - type: constants.cipherType.login, - login: { - uris: null, - username: null, - password: null - }, - fields: null - }; - - var entryStrings = entry.find('> String'); - for (var j = 0; j < entryStrings.length; j++) { - var entryString = $(entryStrings[j]); - - var key = entryString.find('> Key').text(); - var value = entryString.find('> Value').text(); - if (value === '') { - continue; - } - - switch (key) { - case 'URL': - cipher.login.uris = makeUriArray(value); - break; - case 'UserName': - cipher.login.username = value; - break; - case 'Password': - cipher.login.password = value; - break; - case 'Title': - cipher.name = value; - break; - case 'Notes': - cipher.notes = cipher.notes === null ? value + '\n' : cipher.notes + value + '\n'; - break; - default: - if (value.length > 200 || value.indexOf('\n') > -1) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (key + ': ' + value + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - // other custom fields - cipher.fields.push({ - name: key, - value: value, - type: constants.fieldType.text - }); - } - break; - } - } - - if (cipher.name === null) { - cipher.name = '--'; - } - - ciphers.push(cipher); - - if (!isRootNode) { - folderRelationships.push({ - key: cipherIndex, - value: folderIndex - }); - } - } - } - - var groups = node.find('> Group'); - if (groups.length) { - for (var k = 0; k < groups.length; k++) { - traverse($(groups[k]), false, groupName); - } - } - } - } - - function importKeePassXCsv(file, success, error) { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - angular.forEach(results.data, function (value, key) { - value.Group = value.Group.startsWith('Root/') ? - value.Group.replace('Root/', '') : value.Group; - - var groupName = value.Group && value.Group !== '' ? - value.Group.split('/').join(' > ') : null; - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = groupName !== null, - addFolder = hasFolder, - i = 0; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === groupName) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: value.Notes && value.Notes !== '' ? value.Notes : null, - name: value.Title && value.Title !== '' ? value.Title : '--', - login: { - uris: makeUriArray(value.URL), - username: value.Username && value.Username !== '' ? value.Username : null, - password: value.Password && value.Password !== '' ? value.Password : null - } - }; - - if (value.Title) { - ciphers.push(cipher); - } - - if (addFolder) { - folders.push({ - name: groupName - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - }); - - success(folders, ciphers, folderRelationships); - } - }); - } - - function import1Password1Pif(file, success, error) { - var folders = [], - ciphers = [], - i = 0; - - function parseFields(fields, cipher, designationKey, valueKey, nameKey) { - for (var j = 0; j < fields.length; j++) { - var field = fields[j]; - if (!field[valueKey] || field[valueKey] === '') { - continue; - } - - var fieldValue = field[valueKey].toString(); - - if (cipher.type == constants.cipherType.login && !cipher.login.username && - field[designationKey] && field[designationKey] === 'username') { - cipher.login.username = fieldValue; - } - else if (cipher.type == constants.cipherType.login && !cipher.login.password && - field[designationKey] && field[designationKey] === 'password') { - cipher.login.password = fieldValue; - } - else if (cipher.type == constants.cipherType.login && !cipher.login.totp && - field[designationKey] && field[designationKey].startsWith("TOTP_")) { - cipher.login.totp = fieldValue; - } - else if (fieldValue) { - var fieldName = (field[nameKey] || 'no_name'); - if (fieldValue.indexOf('\\n') > -1 || fieldValue.length > 200) { - if (cipher.notes === null) { - cipher.notes = ''; - } - else { - cipher.notes += '\n'; - } - - cipher.notes += (fieldName + ': ' + - fieldValue.split('\\r\\n').join('\n').split('\\n').join('\n')); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: fieldName, - value: fieldValue, - type: constants.fieldType.text - }); - } - } - } - } - - getFileContents(file, parse, error); - - function parse(fileContent) { - var fileLines = fileContent.split(/(?:\r\n|\r|\n)/); - - for (i = 0; i < fileLines.length; i++) { - var line = fileLines[i]; - if (!line.length || line[0] !== '{') { - continue; - } - - var item = JSON.parse(line); - var cipher = { - type: constants.cipherType.login, - favorite: item.openContents && item.openContents.faveIndex ? true : false, - notes: null, - name: item.title && item.title !== '' ? item.title : '--', - fields: null - }; - - if (item.typeName === 'securenotes.SecureNote') { - cipher.type = constants.cipherType.secureNote; - cipher.secureNote = { - type: 0 // generic note - }; - } - else { - cipher.type = constants.cipherType.login; - cipher.login = { - uris: makeUriArray(item.location), - username: null, - password: null, - totp: null - }; - } - - if (item.secureContents) { - if (item.secureContents.notesPlain && item.secureContents.notesPlain !== '') { - cipher.notes = item.secureContents.notesPlain - .split('\\r\\n').join('\n').split('\\n').join('\n'); - } - - if (item.secureContents.fields) { - parseFields(item.secureContents.fields, cipher, 'designation', 'value', 'name'); - } - - if (item.secureContents.sections) { - for (var j = 0; j < item.secureContents.sections.length; j++) { - if (item.secureContents.sections[j].fields) { - parseFields(item.secureContents.sections[j].fields, cipher, 'n', 'v', 't'); - } - } - } - } - - ciphers.push(cipher); - } - - success(folders, ciphers, []); - } - } - - function import1Password6WinCsv(file, success, error) { - var folders = [], - ciphers = []; - - Papa.parse(file, { - encoding: 'UTF-8', - header: true, - complete: function (results) { - parseCsvErrors(results); - - for (var i = 0; i < results.data.length; i++) { - var value = results.data[i]; - if (!value.title) { - continue; - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: value.notesPlain && value.notesPlain !== '' ? value.notesPlain : '', - name: value.title && value.title !== '' ? value.title : '--', - login: { - uris: null, - username: null, - password: null - } - }; - - for (var property in value) { - if (value.hasOwnProperty(property)) { - if (value[property] === null || value[property] === '') { - continue; - } - - if (!cipher.login.password && property === 'password') { - cipher.login.password = value[property]; - } - else if (!cipher.login.username && property === 'username') { - cipher.login.username = value[property]; - } - else if (!cipher.login.uris && property === 'urls') { - var urls = value[property].split(/(?:\r\n|\r|\n)/); - cipher.login.uris = makeUriArray(urls); - } - else if (property !== 'ainfo' && property !== 'autosubmit' && property !== 'notesPlain' && - property !== 'ps' && property !== 'scope' && property !== 'tags' && property !== 'title' && - property !== 'uuid' && !property.startsWith('section:')) { - - if (cipher.notes !== '') { - cipher.notes += '\n'; - } - - cipher.notes += (property + ': ' + value[property]); - } - } - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - } - - success(folders, ciphers, []); - } - }); - } - - function importChromeCsv(file, success, error) { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - angular.forEach(results.data, function (value, key) { - ciphers.push({ - type: constants.cipherType.login, - favorite: false, - notes: null, - name: value.name && value.name !== '' ? value.name : '--', - login: { - uris: makeUriArray(value.url), - username: value.username && value.username !== '' ? value.username : null, - password: value.password && value.password !== '' ? value.password : null - } - }); - }); - - success(folders, ciphers, []); - } - }); - } - - function importFirefoxPasswordExporterCsv(file, success, error) { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - angular.forEach(results.data, function (value, key) { - - ciphers.push({ - type: constants.cipherType.login, - favorite: false, - notes: null, - name: value.hostname && value.hostname !== '' ? loginNameFromUrl(value.hostname) : '--', - login: { - uris: makeUriArray(value.hostname), - username: value.username && value.username !== '' ? value.username : null, - password: value.password && value.password !== '' ? value.password : null - } - }); - }); - - success(folders, ciphers, []); - } - }); - } - - function importUpmCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - angular.forEach(results.data, function (value, key) { - if (value.length === 5) { - ciphers.push({ - type: constants.cipherType.login, - favorite: false, - notes: value[4] && value[4] !== '' ? value[4] : null, - name: value[0] && value[0] !== '' ? value[0] : '--', - login: { - uris: makeUriArray(value[3]), - username: value[1] && value[1] !== '' ? value[1] : null, - password: value[2] && value[2] !== '' ? value[2] : null - } - }); - } - }); - - success(folders, ciphers, []); - } - }); - } - - function importKeeperCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - angular.forEach(results.data, function (value, key) { - if (value.length >= 6) { - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = value[0] && value[0] !== '', - addFolder = hasFolder, - i = 0; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === value[0]) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: value[5] && value[5] !== '' ? value[5] : null, - name: value[1] && value[1] !== '' ? value[1] : '--', - login: { - uris: makeUriArray(value[4]), - username: value[2] && value[2] !== '' ? value[2] : null, - password: value[3] && value[3] !== '' ? value[3] : null - }, - fields: null - }; - - if (value.length > 6) { - // we have some custom fields. - for (i = 6; i < value.length; i = i + 2) { - if (value[i + 1] && value[i + 1].length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (value[i] + ': ' + value[i + 1] + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: value[i], - value: value[i + 1], - type: constants.fieldType.text - }); - } - } - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: value[0] - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - } - }); - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importPasswordDragonXml(file, success, error) { - var folders = [], - ciphers = [], - folderRelationships = [], - foldersIndex = [], - j = 0; - - getXmlFileContents(file, parseXml, error); - - function parseXml(xmlDoc) { - var xml = $(xmlDoc); - - var pwManager = xml.find('PasswordManager'); - if (pwManager.length) { - var records = pwManager.find('> record'); - if (records.length) { - for (var i = 0; i < records.length; i++) { - var record = $(records[i]); - - var accountNameNode = record.find('> Account-Name'), - accountName = accountNameNode.length ? $(accountNameNode) : null, - userIdNode = record.find('> User-Id'), - userId = userIdNode.length ? $(userIdNode) : null, - passwordNode = record.find('> Password'), - password = passwordNode.length ? $(passwordNode) : null, - urlNode = record.find('> URL'), - url = urlNode.length ? $(urlNode) : null, - notesNode = record.find('> Notes'), - notes = notesNode.length ? $(notesNode) : null, - categoryNode = record.find('> Category'), - category = categoryNode.length ? $(categoryNode) : null, - categoryText = category ? category.text() : null; - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = categoryText && categoryText !== '' && categoryText !== 'Unfiled', - addFolder = hasFolder; - - if (hasFolder) { - for (j = 0; j < folders.length; j++) { - if (folders[j].name === categoryText) { - addFolder = false; - folderIndex = j; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: notes && notes.text() !== '' ? notes.text() : null, - name: accountName && accountName.text() !== '' ? accountName.text() : '--', - login: { - uris: url ? makeUriArray(url.text()) : null, - username: userId && userId.text() !== '' ? userId.text() : null, - password: password && password.text() !== '' ? password.text() : null - }, - fields: null - }; - - var attributesSelector = ''; - for (j = 1; j <= 10; j++) { - attributesSelector += '> Attribute-' + j; - if (j < 10) { - attributesSelector += ', '; - } - } - - var attributes = record.find(attributesSelector); - if (attributes.length) { - // we have some attributes. add them as fields - for (j = 0; j < attributes.length; j++) { - var attr = $(attributes[j]), - attrName = attr.prop('tagName'), - attrValue = attr.text(); - - if (!attrValue || attrValue === '' || attrValue === 'null') { - continue; - } - - if (attrValue.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (attrName + ': ' + attrValue + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: attrName, - value: attrValue, - type: constants.fieldType.text - }); - } - } - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: categoryText - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - } - } - - success(folders, ciphers, folderRelationships); - } - else { - error(); - } - } - } - - function importEnpassCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - for (var j = 0; j < results.data.length; j++) { - var row = results.data[j]; - if (row.length < 2) { - continue; - } - if (j === 0 && row[0] === 'Title') { - continue; - } - - var note = row[row.length - 1]; - var cipher = { - type: constants.cipherType.login, - name: row[0], - favorite: false, - notes: note && note !== '' ? note : null, - fields: null, - login: { - uris: null, - password: null, - username: null, - totp: null - } - }; - - if (row.length > 2 && (row.length % 2) === 0) { - for (var i = 0; i < row.length - 2; i += 2) { - var value = row[i + 2]; - if (!value || value === '') { - continue; - } - - var field = row[i + 1]; - var fieldLower = field.toLowerCase(); - - if (fieldLower === 'url' && !cipher.login.uris) { - cipher.login.uris = makeUriArray(value); - } - else if ((fieldLower === 'username' || fieldLower === 'email') && !cipher.login.username) { - cipher.login.username = value; - } - else if (fieldLower === 'password' && !cipher.login.password) { - cipher.login.password = value; - } - else if (fieldLower === 'totp' && !cipher.login.totp) { - cipher.login.totp = value; - } - else if (value.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (field + ': ' + value + '\n'); - } - else { - // other fields - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: field, - value: value, - type: constants.fieldType.text - }); - } - } - } - - ciphers.push(cipher); - } - - success(folders, ciphers, []); - } - }); - } - - function importPasswordSafeXml(file, success, error) { - var folders = [], - ciphers = [], - folderRelationships = [], - foldersIndex = [], - j = 0; - - getXmlFileContents(file, parseXml, error); - - function parseXml(xmlDoc) { - var xml = $(xmlDoc); - - var pwsafe = xml.find('passwordsafe'); - if (pwsafe.length) { - var notesDelimiter = pwsafe.attr('delimiter'); - - var entries = pwsafe.find('> entry'); - if (entries.length) { - for (var i = 0; i < entries.length; i++) { - var entry = $(entries[i]); - - var titleNode = entry.find('> title'), - title = titleNode.length ? $(titleNode) : null, - usernameNode = entry.find('> username'), - username = usernameNode.length ? $(usernameNode) : null, - emailNode = entry.find('> email'), - email = emailNode.length ? $(emailNode) : null, - emailText = email ? email.text() : null, - passwordNode = entry.find('> password'), - password = passwordNode.length ? $(passwordNode) : null, - urlNode = entry.find('> url'), - url = urlNode.length ? $(urlNode) : null, - notesNode = entry.find('> notes'), - notes = notesNode.length ? $(notesNode) : null, - notesText = notes ? notes.text().split(notesDelimiter).join('\n') : null, - groupNode = entry.find('> group'), - group = groupNode.length ? $(groupNode) : null, - groupText = group ? group.text().split('.').join(' > ') : null; - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = groupText && groupText !== '', - addFolder = hasFolder; - - if (hasFolder) { - for (j = 0; j < folders.length; j++) { - if (folders[j].name === groupText) { - addFolder = false; - folderIndex = j; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: notes && notesText !== '' ? notesText : null, - name: title && title.text() !== '' ? title.text() : '--', - login: { - uris: url ? makeUriArray(url.text()) : null, - username: username && username.text() !== '' ? username.text() : null, - password: password && password.text() !== '' ? password.text() : null - } - }; - - if (!cipher.login.username && emailText && emailText !== '') { - cipher.login.username = emailText; - } - else if (emailText && emailText !== '') { - cipher.notes = cipher.notes === null ? 'Email: ' + emailText - : cipher.notes + '\n' + 'Email: ' + emailText; - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: groupText - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - } - } - - success(folders, ciphers, folderRelationships); - } - else { - error(); - } - } - } - - function importDashlaneCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - for (var j = 0; j < results.data.length; j++) { - var skip = false; - var row = results.data[j]; - if (!row.length || row.length === 1) { - continue; - } - - var cipher = { - type: constants.cipherType.login, - name: row[0] && row[0] !== '' ? row[0] : '--', - favorite: false, - notes: null, - login: { - uris: null, - password: null, - username: null - } - }; - - if (row.length === 2) { - cipher.login.uris = makeUriArray(row[1]); - } - else if (row.length === 3) { - cipher.login.uris = makeUriArray(row[1]); - cipher.login.username = row[2]; - } - else if (row.length === 4) { - if (row[2] === '' && row[3] === '') { - cipher.login.username = row[1]; - cipher.notes = row[2] + '\n' + row[3]; - } - else { - cipher.login.username = row[2]; - cipher.notes = row[1] + '\n' + row[3]; - } - } - else if (row.length === 5) { - cipher.login.uris = makeUriArray(row[1]); - cipher.login.username = row[2]; - cipher.login.password = row[3]; - cipher.notes = row[4]; - } - else if (row.length === 6) { - if (row[2] === '') { - cipher.login.username = row[3]; - cipher.login.password = row[4]; - cipher.notes = row[5]; - } - else { - cipher.login.username = row[2]; - cipher.login.password = row[3]; - cipher.notes = row[4] + '\n' + row[5]; - } - - cipher.login.uris = makeUriArray(row[1]); - } - else if (row.length === 7) { - if (row[2] === '') { - cipher.login.username = row[3]; - cipher.notes = row[4] + '\n' + row[6]; - } - else { - cipher.login.username = row[2]; - cipher.notes = row[3] + '\n' + row[4] + '\n' + row[6]; - } - - cipher.login.uris = makeUriArray(row[1]); - cipher.login.password = row[5]; - } - else { - cipher.notes = ''; - for (var i = 1; i < row.length; i++) { - cipher.notes = cipher.notes + row[i] + '\n'; - if (row[i] === 'NO_TYPE') { - skip = true; - break; - } - } - } - - if (skip) { - continue; - } - - if (cipher.login.username === '') { - cipher.login.username = null; - } - if (cipher.login.password === '') { - cipher.login.password = null; - } - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - } - - success(folders, ciphers, []); - } - }); - } - - function importStickyPasswordXml(file, success, error) { - var folders = [], - ciphers = [], - folderRelationships = [], - foldersIndex = [], - j = 0; - - function buildGroupText(database, groupId, groupText) { - var group = database.find('> Groups > Group[ID="' + groupId + '"]'); - if (group.length) { - if (groupText && groupText !== '') { - groupText = ' > ' + groupText; - } - groupText = group.attr('Name') + groupText; - var parentGroupId = group.attr('ParentID'); - return buildGroupText(database, parentGroupId, groupText); - } - return groupText; - } - - getXmlFileContents(file, parseXml, error); - - function parseXml(xmlDoc) { - var xml = $(xmlDoc); - - var database = xml.find('root > Database'); - if (database.length) { - var loginNodes = database.find('> Logins > Login'); - if (loginNodes.length) { - for (var i = 0; i < loginNodes.length; i++) { - var loginNode = $(loginNodes[i]); - - var usernameText = loginNode.attr('Name'), - passwordText = loginNode.attr('Password'), - accountId = loginNode.attr('ID'), - titleText = null, - linkText = null, - notesText = null, - groupId = null, - groupText = null; - - if (accountId && accountId !== '') { - var accountLogin = - database.find('> Accounts > Account > LoginLinks > Login[SourceLoginID="' + accountId + '"]'); - if (accountLogin.length) { - var account = accountLogin.parent().parent(); - if (account.length) { - titleText = account.attr('Name'); - linkText = account.attr('Link'); - groupId = account.attr('ParentID'); - notesText = account.attr('Comments'); - if (notesText) { - notesText = notesText.split('/n').join('\n'); - } - } - } - } - - if (groupId && groupId !== '') { - groupText = buildGroupText(database, groupId, ''); - } - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = groupText && groupText !== '', - addFolder = hasFolder; - - if (hasFolder) { - for (j = 0; j < folders.length; j++) { - if (folders[j].name === groupText) { - addFolder = false; - folderIndex = j; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: notesText && notesText !== '' ? notesText : null, - name: titleText && titleText !== '' ? titleText : '--', - login: { - uris: makeUriArray(linkText), - username: usernameText && usernameText !== '' ? usernameText : null, - password: passwordText && passwordText !== '' ? passwordText : null - } - }; - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: groupText - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - } - } - - success(folders, ciphers, folderRelationships); - } - else { - error(); - } - } - } - - function importmSecureCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - angular.forEach(results.data, function (value, key) { - if (value.length >= 3) { - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = value[0] && value[0] !== '' && value[0] !== 'Unassigned', - addFolder = hasFolder, - i = 0; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === value[0]) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: '', - name: value[2] && value[2] !== '' ? value[2] : null, - login: { - uris: null, - username: null, - password: null - } - }; - - if (value[1] === 'Web Logins') { - cipher.login.uris = makeUriArray(value[4]); - cipher.login.username = value[5] && value[5] !== '' ? value[5] : null; - cipher.login.password = value[6] && value[6] !== '' ? value[6] : null; - cipher.notes = value[3] && value[3] !== '' ? value[3].split('\\n').join('\n') : null; - } - else if (value.length > 3) { - for (var j = 3; j < value.length; j++) { - if (value[j] && value[j] !== '') { - if (cipher.notes !== '') { - cipher.notes = cipher.notes + '\n'; - } - - cipher.notes = cipher.notes + value[j]; - } - } - } - - if (value[1] && value[1] !== '' && value[1] !== 'Web Logins') { - cipher.name = value[1] + ': ' + cipher.name; - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: value[0] - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - } - }); - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importTrueKeyCsv(file, success, error) { - var folders = [], - ciphers = [], - propsToIgnore = [ - 'kind', - 'autologin', - 'favorite', - 'hexcolor', - 'protectedwithpassword', - 'subdomainonly', - 'type', - 'tk_export_version', - 'note', - 'title', - 'document_content' - ]; - - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - angular.forEach(results.data, function (value, key) { - var cipher = { - type: constants.cipherType.login, - favorite: value.favorite && value.favorite.toLowerCase() === 'true' ? true : false, - notes: value.memo && value.memo !== '' ? value.memo : null, - name: value.name && value.name !== '' ? value.name : '--', - login: { - uris: makeUriArray(value.url), - username: value.login && value.login !== '' ? value.login : null, - password: value.password && value.password !== '' ? value.password : null - }, - fields: null - }; - - if (value.kind !== 'login') { - cipher.name = value.title && value.title !== '' ? value.title : '--'; - cipher.notes = value.note && value.note !== '' ? value.note : null; - - if (!cipher.notes) { - cipher.notes = value.document_content && value.document_content !== '' ? - value.document_content : null; - } - - for (var property in value) { - if (value.hasOwnProperty(property) && propsToIgnore.indexOf(property.toLowerCase()) < 0 && - value[property] && value[property] !== '') { - if (value[property].length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (property + ': ' + value[property] + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - // other custom fields - cipher.fields.push({ - name: property, - value: value[property], - type: constants.fieldType.text - }); - } - } - } - } - - ciphers.push(cipher); - }); - - success(folders, ciphers, []); - } - }); - } - - function importClipperzHtml(file, success, error) { - var folders = [], - ciphers = []; - - getFileContents(file, parse, error); - - function parse(fileContents) { - var doc = $(fileContents); - var textarea = doc.find('textarea'); - var json = textarea && textarea.length ? textarea.val() : null; - var entries = json ? JSON.parse(json) : null; - - if (entries && entries.length) { - for (var i = 0; i < entries.length; i++) { - var entry = entries[i]; - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: '', - name: entry.label && entry.label !== '' ? entry.label.split(' ')[0] : '--', - login: { - uris: null, - username: null, - password: null - }, - fields: null - }; - - if (entry.data && entry.data.notes && entry.data.notes !== '') { - cipher.notes = entry.data.notes.split('\\n').join('\n'); - } - - if (entry.currentVersion && entry.currentVersion.fields) { - for (var property in entry.currentVersion.fields) { - if (entry.currentVersion.fields.hasOwnProperty(property)) { - var field = entry.currentVersion.fields[property]; - var actionType = field.actionType.toLowerCase(); - - switch (actionType) { - case 'password': - cipher.login.password = field.value; - break; - case 'email': - case 'username': - case 'user': - case 'name': - cipher.login.username = field.value; - break; - case 'url': - cipher.login.uris = makeUriArray(field.value); - break; - default: - if (!cipher.login.username && isField(field.label, _usernameFieldNames)) { - cipher.login.username = field.value; - } - else if (!cipher.login.password && isField(field.label, _passwordFieldNames)) { - cipher.login.password = field.value; - } - else if (field.value.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (field.label + ': ' + field.value + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - cipher.fields.push({ - name: field.label, - value: field.value, - type: constants.fieldType.text - }); - } - break; - } - } - } - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - } - } - - success(folders, ciphers, []); - } - } - - function importAviraJson(file, success, error) { - var folders = [], - ciphers = [], - i = 0; - - getFileContents(file, parseJson, error); - - function parseJson(fileContent) { - var fileJson = JSON.parse(fileContent); - if (fileJson) { - if (fileJson.accounts) { - for (i = 0; i < fileJson.accounts.length; i++) { - var account = fileJson.accounts[i]; - var cipher = { - type: constants.cipherType.login, - favorite: account.is_favorite && account.is_favorite === true, - notes: null, - name: account.label && account.label !== '' ? account.label : account.domain, - login: { - uris: makeUriArray(account.domain), - username: account.username && account.username !== '' ? account.username : null, - password: account.password && account.password !== '' ? account.password : null - } - }; - - if (account.email && account.email !== '') { - if (!cipher.login.username || cipher.login.username === '') { - cipher.login.username = account.email; - } - else { - cipher.notes = account.email; - } - } - - if (!cipher.name || cipher.name === '') { - cipher.name = '--'; - } - - ciphers.push(cipher); - } - } - } - - success(folders, ciphers, []); - } - } - - function importRoboFormHtml(file, success, error) { - var folders = [], - ciphers = []; - - getFileContents(file, parse, error); - - function parse(fileContents) { - var doc = $(fileContents.split('­').join('').split('').join('')); - var outterTables = doc.find('table.nobr'); - if (outterTables.length) { - for (var i = 0; i < outterTables.length; i++) { - var outterTable = $(outterTables[i]); - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: '', - name: outterTable.find('span.caption').text(), - login: { - uris: null, - username: null, - password: null - }, - fields: null - }; - - var url = outterTable.find('.subcaption').text(); - if (url && url !== '') { - cipher.login.uris = makeUriArray(url); - } - - var fields = []; - /* jshint ignore:start */ - $.each(outterTable.find('table td:not(.subcaption)'), function (indexInArray, valueOfElement) { - $(valueOfElement).find('br').replaceWith('\n'); - var t = $(valueOfElement).text(); - if (t !== '') { - fields.push(t.split('\\n').join('\n')); - } - }); - /* jshint ignore:end */ - - if (fields.length && (fields.length % 2 === 0)) - for (var j = 0; j < fields.length; j += 2) { - var field = fields[j]; - var fieldValue = fields[j + 1]; - - if (!cipher.login.password && isField(field.replace(':', ''), _passwordFieldNames)) { - cipher.login.password = fieldValue; - } - else if (!cipher.login.username && isField(field.replace(':', ''), _usernameFieldNames)) { - cipher.login.username = fieldValue; - } - else if (fieldValue.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (field + ': ' + fieldValue + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: field, - value: fieldValue, - type: constants.fieldType.text - }); - } - } - - if (!cipher.notes || cipher.notes === '') { - cipher.notes = null; - } - - if (!cipher.name || cipher.name === '') { - cipher.name = '--'; - } - - ciphers.push(cipher); - } - } - - success(folders, ciphers, []); - } - } - - function importSaferPassCsv(file, success, error) { - var folders = [], - ciphers = []; - - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - angular.forEach(results.data, function (value, key) { - ciphers.push({ - type: constants.cipherType.login, - favorite: false, - notes: value.notes && value.notes !== '' ? value.notes : null, - name: value.url && value.url !== '' ? loginNameFromUrl(value.url) : '--', - login: { - uris: makeUriArray(value.url), - username: value.username && value.username !== '' ? value.username : null, - password: value.password && value.password !== '' ? value.password : null - } - }); - }); - - success(folders, ciphers, []); - } - }); - } - - function importAscendoCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - for (var j = 0; j < results.data.length; j++) { - var row = results.data[j]; - if (row.length < 2) { - continue; - } - - var note = row[row.length - 1]; - var cipher = { - type: constants.cipherType.login, - name: row[0], - favorite: false, - notes: note && note !== '' ? note : null, - login: { - uris: null, - password: null, - username: null - }, - fields: null - }; - - if (row.length > 2 && (row.length % 2) === 0) { - for (var i = 0; i < row.length - 2; i += 2) { - var value = row[i + 2]; - var field = row[i + 1]; - if (!field || field === '' || !value || value === '') { - continue; - } - - var fieldLower = field.toLowerCase(); - - if (!cipher.login.uris && isField(field, _uriFieldNames)) { - cipher.login.uris = makeUriArray(value); - } - else if (!cipher.login.username && isField(field, _usernameFieldNames)) { - cipher.login.username = value; - } - else if (!cipher.login.password && isField(field, _passwordFieldNames)) { - cipher.login.password = value; - } - else if (value.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (field + ': ' + value + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - // other custom fields - cipher.fields.push({ - name: field, - value: value, - type: constants.fieldType.text - }); - } - } - } - - ciphers.push(cipher); - } - - success(folders, ciphers, []); - } - }); - } - - function importPasswordBossJson(file, success, error) { - var folders = [], - ciphers = [], - i = 0; - - getFileContents(file, parseJson, error); - - function parseJson(fileContent) { - var fileJson = JSON.parse(fileContent); - if (fileJson && fileJson.length) { - for (i = 0; i < fileJson.length; i++) { - var item = fileJson[i]; - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: '', - name: item.name && item.name !== '' ? item.name : '--', - login: { - uris: makeUriArray(item.login_url), - username: null, - password: null - }, - fields: null - }; - - if (!item.identifiers) { - continue; - } - - if (item.identifiers.notes && item.identifiers.notes !== '') { - cipher.notes = item.identifiers.notes.split('\\r\\n').join('\n').split('\\n').join('\n'); - } - - for (var property in item.identifiers) { - if (item.identifiers.hasOwnProperty(property)) { - var value = item.identifiers[property]; - if (property === 'notes' || value === '' || value === null) { - continue; - } - - if (property === 'username') { - cipher.login.username = value; - } - else if (property === 'password') { - cipher.login.password = value; - } - else if (value.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (property + ': ' + value + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: property, - value: value, - type: constants.fieldType.text - }); - } - } - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - } - } - - success(folders, ciphers, []); - } - } - - function importZohoVaultCsv(file, success, error) { - function parseData(data, cipher) { - if (!data || data === '') { - return; - } - - var dataLines = data.split(/(?:\r\n|\r|\n)/); - for (var i = 0; i < dataLines.length; i++) { - var line = dataLines[i]; - var delimPosition = line.indexOf(':'); - if (delimPosition < 0) { - continue; - } - - var field = line.substring(0, delimPosition); - var value = line.length > delimPosition ? line.substring(delimPosition + 1) : null; - if (!field || field === '' || !value || value === '' || field === 'SecretType') { - continue; - } - - var fieldLower = field.toLowerCase(); - if (fieldLower === 'user name') { - cipher.login.username = value; - } - else if (fieldLower === 'password') { - cipher.login.password = value; - } - else if (value.length > 200) { - if (!cipher.notes) { - cipher.notes = ''; - } - - cipher.notes += (field + ': ' + value + '\n'); - } - else { - if (!cipher.fields) { - cipher.fields = []; - } - - cipher.fields.push({ - name: field, - value: value, - type: constants.fieldType.text - }); - } - } - } - - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - angular.forEach(results.data, function (value, key) { - var chamber = value.ChamberName; - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = chamber && chamber !== '', - addFolder = hasFolder, - i = 0; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === chamber) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: value.Favorite && value.Favorite === '1' ? true : false, - notes: value.Notes && value.Notes !== '' ? value.Notes : '', - name: value['Secret Name'] && value['Secret Name'] !== '' ? value['Secret Name'] : '--', - login: { - uris: makeUriArray(value['Secret URL']), - username: null, - password: null - }, - fields: null - }; - - parseData(value.SecretData, cipher); - parseData(value.CustomData, cipher); - - if (cipher.notes === '') { - cipher.notes = null; - } - - if (value['Secret Name']) { - ciphers.push(cipher); - } - - if (addFolder) { - folders.push({ - name: chamber - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - }); - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importSplashIdCsv(file, success, error) { - Papa.parse(file, { - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - function parseFieldsToNotes(startIndex, row, cipher) { - // last 3 rows do not get parsed - for (var k = startIndex; k < row.length - 3; k++) { - if (!row[k] || row[k] === '') { - continue; - } - - if (!cipher.notes) { - cipher.notes = ''; - } - else if (cipher.notes !== '') { - cipher.notes += '\n'; - } - - cipher.notes += row[k]; - } - } - - // skip 1st row since its not data - for (var i = 1; i < results.data.length; i++) { - if (results.data[i].length < 3) { - continue; - } - - var value = results.data[i], - category = value[results.data.length - 1], - notes = value[results.data.length - 2], - type = value[0]; - - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = category && category !== '' && category !== 'Unfiled', - addFolder = hasFolder, - j = 0; - - if (hasFolder) { - for (j = 0; j < folders.length; j++) { - if (folders[j].name === category) { - addFolder = false; - folderIndex = j; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: notes, - name: value[1] && value[1] !== '' ? value[1] : '--', - fields: null, - login: { - uris: null, - username: null, - password: null - } - }; - - if (type === 'Web Logins' || type === 'Servers' || type === 'Email Accounts') { - cipher.login.uris = makeUriArray(value[4]); - cipher.login.username = value[2] && value[2] !== '' ? value[2] : null; - cipher.login.password = value[3] && value[3] !== '' ? value[3] : null; - parseFieldsToNotes(5, value, cipher); - } - else if (value.length > 2) { - parseFieldsToNotes(2, value, cipher); - } - - if (cipher.name && cipher.name !== '--' && type !== 'Web Logins' && type !== 'Servers' && - type !== 'Email Accounts') { - cipher.name = type + ': ' + cipher.name; - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: category - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - } - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importMeldiumCsv(file, success, error) { - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = []; - - for (var j = 0; j < results.data.length; j++) { - var row = results.data[j]; - var cipher = { - type: constants.cipherType.login, - name: row.DisplayName && row.DisplayName !== '' ? row.DisplayName : '--', - favorite: false, - notes: row.Notes && row.Notes !== '' ? row.Notes : null, - login: { - uris: makeUriArray(row.Url), - password: row.Password && row.Password !== '' ? row.Password : null, - username: row.UserName && row.UserName !== '' ? row.UserName : null - } - }; - - ciphers.push(cipher); - } - - success(folders, ciphers, []); - } - }); - } - - function importPassKeepCsv(file, success, error) { - function getValue(key, obj) { - var val = obj[key] || obj[(' ' + key)]; - if (val && val !== '') { - return val; - } - - return null; - } - - Papa.parse(file, { - header: true, - encoding: 'UTF-8', - complete: function (results) { - parseCsvErrors(results); - - var folders = [], - ciphers = [], - folderRelationships = []; - - angular.forEach(results.data, function (value, key) { - var folderIndex = folders.length, - cipherIndex = ciphers.length, - hasFolder = !!getValue('category', value), - addFolder = hasFolder, - i = 0; - - if (hasFolder) { - for (i = 0; i < folders.length; i++) { - if (folders[i].name === getValue('category', value)) { - addFolder = false; - folderIndex = i; - break; - } - } - } - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: !!getValue('description', value) ? getValue('description', value) : null, - name: !!getValue('title', value) ? getValue('title', value) : '--', - login: { - uris: !!getValue('site', value) ? makeUriArray(getValue('site', value)) : null, - username: !!getValue('username', value) ? getValue('username', value) : null, - password: !!getValue('password', value) ? getValue('password', value) : null - } - }; - - if (!!getValue('password2', value)) { - if (!cipher.notes) { - cipher.notes = ''; - } - else { - cipher.notes += '\n'; - } - - cipher.notes += ('Password 2: ' + getValue('password2', value)); - } - - ciphers.push(cipher); - - if (addFolder) { - folders.push({ - name: getValue('category', value) - }); - } - - if (hasFolder) { - var relationship = { - key: cipherIndex, - value: folderIndex - }; - folderRelationships.push(relationship); - } - }); - - success(folders, ciphers, folderRelationships); - } - }); - } - - function importGnomeJson(file, success, error) { - var folders = [], - ciphers = [], - folderRelationships = [], - i = 0; - - getFileContents(file, parseJson, error); - - function parseJson(fileContent) { - var fileJson = JSON.parse(fileContent); - var folderIndex = 0; - var cipherIndex = 0; - - if (fileJson && Object.keys(fileJson).length) { - for (var keyRing in fileJson) { - if (fileJson.hasOwnProperty(keyRing) && fileJson[keyRing].length) { - folderIndex = folders.length; - folders.push({ - name: keyRing - }); - - for (i = 0; i < fileJson[keyRing].length; i++) { - var item = fileJson[keyRing][i]; - if (!item.display_name || item.display_name.indexOf('http') !== 0) { - continue; - } - - cipherIndex = ciphers.length; - - var cipher = { - type: constants.cipherType.login, - favorite: false, - notes: '', - name: item.display_name.replace('http://', '').replace('https://', ''), - login: { - uris: makeUriArray(item.display_name), - username: item.attributes.username_value && item.attributes.username_value !== '' ? - item.attributes.username_value : null, - password: item.secret && item.secret !== '' ? item.secret : null - } - }; - - if (cipher.name > 30) { - cipher.name = cipher.name.substring(0, 30); - } - - for (var attr in item.attributes) { - if (item.attributes.hasOwnProperty(attr) && attr !== 'username_value' && - attr !== 'xdg:schema') { - if (cipher.notes !== '') { - cipher.notes += '\n'; - } - cipher.notes += (attr + ': ' + item.attributes[attr]); - } - } - - if (cipher.notes === '') { - cipher.notes = null; - } - - ciphers.push(cipher); - folderRelationships.push({ - key: cipherIndex, - value: folderIndex - }); - } - } - } - } - - success(folders, ciphers, folderRelationships); - } - } - - return _service; - }); diff --git a/src/app/services/organization-guard.service.ts b/src/app/services/organization-guard.service.ts new file mode 100644 index 0000000000..4ee4b94756 --- /dev/null +++ b/src/app/services/organization-guard.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + CanActivate, + Router, +} from '@angular/router'; + +import { UserService } from 'jslib/abstractions/user.service'; + +@Injectable() +export class OrganizationGuardService implements CanActivate { + constructor(private userService: UserService, private router: Router) { } + + async canActivate(route: ActivatedRouteSnapshot) { + const org = await this.userService.getOrganization(route.params.organizationId); + if (org == null) { + this.router.navigate(['/']); + return false; + } + + return true; + } +} diff --git a/src/app/services/organization-type-guard.service.ts b/src/app/services/organization-type-guard.service.ts new file mode 100644 index 0000000000..c4f2f64e1b --- /dev/null +++ b/src/app/services/organization-type-guard.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + CanActivate, + Router, +} from '@angular/router'; + +import { UserService } from 'jslib/abstractions/user.service'; + +import { OrganizationUserType } from 'jslib/enums/organizationUserType'; + +@Injectable() +export class OrganizationTypeGuardService implements CanActivate { + constructor(private userService: UserService, private router: Router) { } + + async canActivate(route: ActivatedRouteSnapshot) { + const org = await this.userService.getOrganization(route.parent.params.organizationId); + const allowedTypes = route.data == null ? null : route.data.allowedTypes as OrganizationUserType[]; + if (allowedTypes == null || allowedTypes.indexOf(org.type) === -1) { + this.router.navigate(['/organizations', org.id]); + return false; + } + + return true; + } +} diff --git a/src/app/services/passwordService.js b/src/app/services/passwordService.js deleted file mode 100644 index 54504f809b..0000000000 --- a/src/app/services/passwordService.js +++ /dev/null @@ -1,136 +0,0 @@ -angular - .module('bit.services') - - .factory('passwordService', function () { - var _service = {}; - - _service.generatePassword = function (options) { - var defaults = { - length: 10, - ambiguous: false, - number: true, - minNumber: 1, - uppercase: true, - minUppercase: 1, - lowercase: true, - minLowercase: 1, - special: false, - minSpecial: 1 - }; - - // overload defaults with given options - var o = angular.extend({}, defaults, options); - - // sanitize - if (o.uppercase && o.minUppercase < 0) o.minUppercase = 1; - if (o.lowercase && o.minLowercase < 0) o.minLowercase = 1; - if (o.number && o.minNumber < 0) o.minNumber = 1; - if (o.special && o.minSpecial < 0) o.minSpecial = 1; - - if (!o.length || o.length < 1) o.length = 10; - var minLength = o.minUppercase + o.minLowercase + o.minNumber + o.minSpecial; - if (o.length < minLength) o.length = minLength; - - var positions = []; - if (o.lowercase && o.minLowercase > 0) { - for (var i = 0; i < o.minLowercase; i++) { - positions.push('l'); - } - } - if (o.uppercase && o.minUppercase > 0) { - for (var j = 0; j < o.minUppercase; j++) { - positions.push('u'); - } - } - if (o.number && o.minNumber > 0) { - for (var k = 0; k < o.minNumber; k++) { - positions.push('n'); - } - } - if (o.special && o.minSpecial > 0) { - for (var l = 0; l < o.minSpecial; l++) { - positions.push('s'); - } - } - while (positions.length < o.length) { - positions.push('a'); - } - - // shuffle - positions.sort(function () { - return randomInt(0, 1) * 2 - 1; - }); - - // build out the char sets - var allCharSet = ''; - - var lowercaseCharSet = 'abcdefghijkmnopqrstuvwxyz'; - if (o.ambiguous) lowercaseCharSet += 'l'; - if (o.lowercase) allCharSet += lowercaseCharSet; - - var uppercaseCharSet = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'; - if (o.ambiguous) uppercaseCharSet += 'O'; - if (o.uppercase) allCharSet += uppercaseCharSet; - - var numberCharSet = '23456789'; - if (o.ambiguous) numberCharSet += '01'; - if (o.number) allCharSet += numberCharSet; - - var specialCharSet = '!@#$%^&*'; - if (o.special) allCharSet += specialCharSet; - - var password = ''; - for (var m = 0; m < o.length; m++) { - var positionChars; - switch (positions[m]) { - case 'l': positionChars = lowercaseCharSet; break; - case 'u': positionChars = uppercaseCharSet; break; - case 'n': positionChars = numberCharSet; break; - case 's': positionChars = specialCharSet; break; - case 'a': positionChars = allCharSet; break; - } - - var randomCharIndex = randomInt(0, positionChars.length - 1); - password += positionChars.charAt(randomCharIndex); - } - - return password; - }; - - // EFForg/OpenWireless - // ref https://github.com/EFForg/OpenWireless/blob/master/app/js/diceware.js - function randomInt(min, max) { - var rval = 0; - var range = max - min; - - var bits_needed = Math.ceil(Math.log2(range)); - if (bits_needed > 53) { - throw new Exception("We cannot generate numbers larger than 53 bits."); - } - var bytes_needed = Math.ceil(bits_needed / 8); - var mask = Math.pow(2, bits_needed) - 1; - // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 - - // Create byte array and fill with N random numbers - var byteArray = new Uint8Array(bytes_needed); - window.crypto.getRandomValues(byteArray); - - var p = (bytes_needed - 1) * 8; - for (var i = 0; i < bytes_needed; i++) { - rval += byteArray[i] * Math.pow(2, p); - p -= 8; - } - - // Use & to apply the mask and reduce the number of recursive lookups - rval = rval & mask; - - if (rval >= range) { - // Integer out of acceptable range - return randomInt(min, max); - } - // Return an integer that falls within the range - return min + rval; - } - - return _service; - }); diff --git a/src/app/services/router.service.ts b/src/app/services/router.service.ts new file mode 100644 index 0000000000..b3ffd181a4 --- /dev/null +++ b/src/app/services/router.service.ts @@ -0,0 +1,58 @@ +import { Injectable } from '@angular/core'; +import { Title } from '@angular/platform-browser'; +import { + ActivatedRoute, + NavigationEnd, + Router, +} from '@angular/router'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; + +@Injectable() +export class RouterService { + private previousUrl: string = undefined; + private currentUrl: string = undefined; + + constructor(private router: Router, private activatedRoute: ActivatedRoute, + private titleService: Title, private i18nService: I18nService) { + this.currentUrl = this.router.url; + router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + this.previousUrl = this.currentUrl; + this.currentUrl = event.url; + + let title = i18nService.t('pageTitle', 'Bitwarden'); + let titleId: string = null; + let rawTitle: string = null; + let child = this.activatedRoute.firstChild; + while (child != null) { + if (child.firstChild != null) { + child = child.firstChild; + } else if (child.snapshot.data != null && child.snapshot.data.title != null) { + rawTitle = child.snapshot.data.title; + break; + } else if (child.snapshot.data != null && child.snapshot.data.titleId != null) { + titleId = child.snapshot.data.titleId; + break; + } else { + titleId = null; + rawTitle = null; + break; + } + } + + if (titleId != null || rawTitle != null) { + const newTitle = rawTitle != null ? rawTitle : i18nService.t(titleId); + if (newTitle != null && newTitle !== '') { + title = (newTitle + ' | ' + title); + } + } + this.titleService.setTitle(title); + } + }); + } + + getPreviousUrl() { + return this.previousUrl; + } +} diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts new file mode 100644 index 0000000000..10c9798992 --- /dev/null +++ b/src/app/services/services.module.ts @@ -0,0 +1,184 @@ +import { + APP_INITIALIZER, + NgModule, +} from '@angular/core'; + +import { ToasterModule } from 'angular2-toaster'; + +import { BroadcasterMessagingService } from '../../services/broadcasterMessaging.service'; +import { HtmlStorageService } from '../../services/htmlStorage.service'; +import { I18nService } from '../../services/i18n.service'; +import { MemoryStorageService } from '../../services/memoryStorage.service'; +import { WebPlatformUtilsService } from '../../services/webPlatformUtils.service'; + +import { EventService } from './event.service'; +import { OrganizationGuardService } from './organization-guard.service'; +import { OrganizationTypeGuardService } from './organization-type-guard.service'; +import { RouterService } from './router.service'; +import { UnauthGuardService } from './unauth-guard.service'; + +import { AuthGuardService } from 'jslib/angular/services/auth-guard.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; +import { ValidationService } from 'jslib/angular/services/validation.service'; + +import { Analytics } from 'jslib/misc/analytics'; + +import { ApiService } from 'jslib/services/api.service'; +import { AppIdService } from 'jslib/services/appId.service'; +import { AuditService } from 'jslib/services/audit.service'; +import { AuthService } from 'jslib/services/auth.service'; +import { CipherService } from 'jslib/services/cipher.service'; +import { CollectionService } from 'jslib/services/collection.service'; +import { ConstantsService } from 'jslib/services/constants.service'; +import { ContainerService } from 'jslib/services/container.service'; +import { CryptoService } from 'jslib/services/crypto.service'; +import { EnvironmentService } from 'jslib/services/environment.service'; +import { ExportService } from 'jslib/services/export.service'; +import { FolderService } from 'jslib/services/folder.service'; +import { LockService } from 'jslib/services/lock.service'; +import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service'; +import { SettingsService } from 'jslib/services/settings.service'; +import { StateService } from 'jslib/services/state.service'; +import { SyncService } from 'jslib/services/sync.service'; +import { TokenService } from 'jslib/services/token.service'; +import { TotpService } from 'jslib/services/totp.service'; +import { UserService } from 'jslib/services/user.service'; +import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service'; + +import { ApiService as ApiServiceAbstraction } from 'jslib/abstractions/api.service'; +import { AppIdService as AppIdServiceAbstraction } from 'jslib/abstractions/appId.service'; +import { AuditService as AuditServiceAbstraction } from 'jslib/abstractions/audit.service'; +import { AuthService as AuthServiceAbstraction } from 'jslib/abstractions/auth.service'; +import { CipherService as CipherServiceAbstraction } from 'jslib/abstractions/cipher.service'; +import { CollectionService as CollectionServiceAbstraction } from 'jslib/abstractions/collection.service'; +import { CryptoService as CryptoServiceAbstraction } from 'jslib/abstractions/crypto.service'; +import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib/abstractions/cryptoFunction.service'; +import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib/abstractions/environment.service'; +import { ExportService as ExportServiceAbstraction } from 'jslib/abstractions/export.service'; +import { FolderService as FolderServiceAbstraction } from 'jslib/abstractions/folder.service'; +import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service'; +import { LockService as LockServiceAbstraction } from 'jslib/abstractions/lock.service'; +import { LogService as LogServiceAbstraction } from 'jslib/abstractions/log.service'; +import { MessagingService as MessagingServiceAbstraction } from 'jslib/abstractions/messaging.service'; +import { + PasswordGenerationService as PasswordGenerationServiceAbstraction, +} from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib/abstractions/platformUtils.service'; +import { SettingsService as SettingsServiceAbstraction } from 'jslib/abstractions/settings.service'; +import { StateService as StateServiceAbstraction } from 'jslib/abstractions/state.service'; +import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service'; +import { SyncService as SyncServiceAbstraction } from 'jslib/abstractions/sync.service'; +import { TokenService as TokenServiceAbstraction } from 'jslib/abstractions/token.service'; +import { TotpService as TotpServiceAbstraction } from 'jslib/abstractions/totp.service'; +import { UserService as UserServiceAbstraction } from 'jslib/abstractions/user.service'; + +const i18nService = new I18nService(window.navigator.language, 'locales'); +const stateService = new StateService(); +const broadcasterService = new BroadcasterService(); +const messagingService = new BroadcasterMessagingService(broadcasterService); +const platformUtilsService = new WebPlatformUtilsService(i18nService); +const storageService: StorageServiceAbstraction = new HtmlStorageService(); +const secureStorageService: StorageServiceAbstraction = new MemoryStorageService(); +const cryptoFunctionService: CryptoFunctionServiceAbstraction = new WebCryptoFunctionService(window, + platformUtilsService); +const cryptoService = new CryptoService(storageService, + platformUtilsService.isDev() ? storageService : secureStorageService, cryptoFunctionService); +const tokenService = new TokenService(storageService); +const appIdService = new AppIdService(storageService); +const apiService = new ApiService(tokenService, platformUtilsService, + async (expired: boolean) => messagingService.send('logout', { expired: expired })); +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, i18nService, platformUtilsService); +const folderService = new FolderService(cryptoService, userService, apiService, storageService, + i18nService, cipherService); +const collectionService = new CollectionService(cryptoService, userService, storageService, i18nService); +const lockService = new LockService(cipherService, folderService, collectionService, + cryptoService, platformUtilsService, storageService, messagingService, null); +const syncService = new SyncService(userService, apiService, settingsService, + folderService, cipherService, cryptoService, collectionService, storageService, messagingService, + async (expired: boolean) => messagingService.send('logout', { expired: expired })); +const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService); +const totpService = new TotpService(storageService, cryptoFunctionService); +const containerService = new ContainerService(cryptoService, platformUtilsService); +const authService = new AuthService(cryptoService, apiService, + userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService); +const exportService = new ExportService(folderService, cipherService, apiService); +const auditService = new AuditService(cryptoFunctionService, apiService); + +const analytics = new Analytics(window, () => platformUtilsService.isDev(), + platformUtilsService, storageService, appIdService); +containerService.attachToWindow(window); + +export function initFactory(): Function { + return async () => { + const isDev = platformUtilsService.isDev(); + await apiService.setUrls({ + base: isDev ? null : window.location.origin, + api: isDev ? 'http://localhost:4000' : null, + identity: isDev ? 'http://localhost:33656' : null, + }); + + lockService.init(true); + const locale = await storageService.get(ConstantsService.localeKey); + await i18nService.init(locale); + await authService.init(); + const htmlEl = window.document.documentElement; + htmlEl.classList.add('locale_' + i18nService.translationLocale); + let theme = await storageService.get(ConstantsService.themeKey); + if (theme == null) { + theme = 'light'; + } + htmlEl.classList.add('theme_' + theme); + stateService.save(ConstantsService.disableFaviconKey, + await storageService.get(ConstantsService.disableFaviconKey)); + }; +} + +@NgModule({ + imports: [ + ToasterModule, + ], + declarations: [], + providers: [ + ValidationService, + AuthGuardService, + OrganizationGuardService, + OrganizationTypeGuardService, + UnauthGuardService, + RouterService, + EventService, + { provide: AuditServiceAbstraction, useValue: auditService }, + { provide: AuthServiceAbstraction, useValue: authService }, + { provide: CipherServiceAbstraction, useValue: cipherService }, + { provide: FolderServiceAbstraction, useValue: folderService }, + { provide: CollectionServiceAbstraction, useValue: collectionService }, + { provide: EnvironmentServiceAbstraction, useValue: environmentService }, + { provide: TotpServiceAbstraction, useValue: totpService }, + { provide: TokenServiceAbstraction, useValue: tokenService }, + { provide: I18nServiceAbstraction, useValue: i18nService }, + { provide: CryptoServiceAbstraction, useValue: cryptoService }, + { provide: PlatformUtilsServiceAbstraction, useValue: platformUtilsService }, + { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, + { provide: ApiServiceAbstraction, useValue: apiService }, + { provide: SyncServiceAbstraction, useValue: syncService }, + { provide: UserServiceAbstraction, useValue: userService }, + { provide: MessagingServiceAbstraction, useValue: messagingService }, + { provide: BroadcasterService, useValue: broadcasterService }, + { provide: SettingsServiceAbstraction, useValue: settingsService }, + { provide: LockServiceAbstraction, useValue: lockService }, + { provide: StorageServiceAbstraction, useValue: storageService }, + { provide: StateServiceAbstraction, useValue: stateService }, + { provide: ExportServiceAbstraction, useValue: exportService }, + { + provide: APP_INITIALIZER, + useFactory: initFactory, + deps: [], + multi: true, + }, + ], +}) +export class ServicesModule { +} diff --git a/src/app/services/servicesModule.js b/src/app/services/servicesModule.js deleted file mode 100644 index 0fbfca98db..0000000000 --- a/src/app/services/servicesModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.services', ['ngResource', 'ngStorage', 'angular-jwt']); diff --git a/src/app/services/tokenService.js b/src/app/services/tokenService.js deleted file mode 100644 index 3c66b8b4fc..0000000000 --- a/src/app/services/tokenService.js +++ /dev/null @@ -1,90 +0,0 @@ -angular - .module('bit.services') - - .factory('tokenService', function ($sessionStorage, $localStorage, jwtHelper) { - var _service = {}, - _token = null, - _refreshToken = null; - - _service.setToken = function (token) { - $sessionStorage.accessToken = token; - _token = token; - }; - - _service.getToken = function () { - if (!_token) { - _token = $sessionStorage.accessToken; - } - - return _token ? _token : null; - }; - - _service.clearToken = function () { - _token = null; - delete $sessionStorage.accessToken; - }; - - _service.setRefreshToken = function (token) { - $sessionStorage.refreshToken = token; - _refreshToken = token; - }; - - _service.getRefreshToken = function () { - if (!_refreshToken) { - _refreshToken = $sessionStorage.refreshToken; - } - - return _refreshToken ? _refreshToken : null; - }; - - _service.clearRefreshToken = function () { - _refreshToken = null; - delete $sessionStorage.refreshToken; - }; - - _service.setTwoFactorToken = function (token, email) { - if (!$localStorage.twoFactor) { - $localStorage.twoFactor = {}; - } - $localStorage.twoFactor[email] = token; - }; - - _service.getTwoFactorToken = function (email) { - return $localStorage.twoFactor ? $localStorage.twoFactor[email] : null; - }; - - _service.clearTwoFactorToken = function (email) { - if (email) { - if ($localStorage.twoFactor && $localStorage.twoFactor[email]) { - delete $localStorage.twoFactor[email]; - } - } - else { - delete $localStorage.twoFactor; - } - }; - - _service.clearTokens = function () { - _service.clearToken(); - _service.clearRefreshToken(); - }; - - _service.tokenSecondsRemaining = function (token, offsetSeconds) { - var d = jwtHelper.getTokenExpirationDate(token); - offsetSeconds = offsetSeconds || 0; - if (d === null) { - return 0; - } - - var msRemaining = d.valueOf() - (new Date().valueOf() + (offsetSeconds * 1000)); - return Math.round(msRemaining / 1000); - }; - - _service.tokenNeedsRefresh = function (token, minutes) { - minutes = minutes || 5; // default 5 minutes - var sRemaining = _service.tokenSecondsRemaining(token); - return sRemaining < (60 * minutes); - }; - - return _service; - }); diff --git a/src/app/services/unauth-guard.service.ts b/src/app/services/unauth-guard.service.ts new file mode 100644 index 0000000000..3b86cd6042 --- /dev/null +++ b/src/app/services/unauth-guard.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { + CanActivate, + Router, +} from '@angular/router'; + +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +@Injectable() +export class UnauthGuardService implements CanActivate { + constructor(private cryptoService: CryptoService, private userService: UserService, + private router: Router) { } + + async canActivate() { + const isAuthed = await this.userService.isAuthenticated(); + if (isAuthed) { + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + this.router.navigate(['lock']); + } else { + this.router.navigate(['vault']); + } + return false; + } + + return true; + } +} diff --git a/src/app/services/utilsService.js b/src/app/services/utilsService.js deleted file mode 100644 index f787b418be..0000000000 --- a/src/app/services/utilsService.js +++ /dev/null @@ -1,47 +0,0 @@ -angular - .module('bit.services') - - .factory('utilsService', function (constants) { - var _service = {}; - var _browserCache; - - _service.getDeviceType = function (token) { - if (_browserCache) { - return _browserCache; - } - - if (navigator.userAgent.indexOf(' Vivaldi/') >= 0) { - _browserCache = constants.deviceType.vivaldi; - } - else if (!!window.chrome && !!window.chrome.webstore) { - _browserCache = constants.deviceType.chrome; - } - else if (typeof InstallTrigger !== 'undefined') { - _browserCache = constants.deviceType.firefox; - } - else if ((!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) { - _browserCache = constants.deviceType.firefox; - } - else if (/constructor/i.test(window.HTMLElement) || - safariCheck(!window.safari || (typeof safari !== 'undefined' && safari.pushNotification))) { - _browserCache = constants.deviceType.opera; - } - else if (!!document.documentMode) { - _browserCache = constants.deviceType.ie; - } - else if (!!window.StyleMedia) { - _browserCache = constants.deviceType.edge; - } - else { - _browserCache = constants.deviceType.unknown; - } - - return _browserCache; - }; - - function safariCheck(p) { - return p.toString() === '[object SafariRemoteNotification]'; - } - - return _service; - }); diff --git a/src/app/services/validationService.js b/src/app/services/validationService.js deleted file mode 100644 index 1e83b2eb23..0000000000 --- a/src/app/services/validationService.js +++ /dev/null @@ -1,102 +0,0 @@ -angular - .module('bit.services') - - .factory('validationService', function () { - var _service = {}; - - _service.addErrors = function (form, reason) { - var data = reason.data; - var defaultErrorMessage = 'An unexpected error has occurred.'; - form.$errors = []; - - if (!data || !angular.isObject(data)) { - form.$errors.push(defaultErrorMessage); - return; - } - - if (data && data.ErrorModel) { - data = data.ErrorModel; - } - - if (!data.ValidationErrors) { - if (data.Message) { - form.$errors.push(data.Message); - } - else { - form.$errors.push(defaultErrorMessage); - } - - return; - } - - for (var key in data.ValidationErrors) { - if (!data.ValidationErrors.hasOwnProperty(key)) { - continue; - } - - for (var i = 0; i < data.ValidationErrors[key].length; i++) { - _service.addError(form, key, data.ValidationErrors[key][i]); - } - } - }; - - _service.addError = function (form, key, errorMessage, clearExistingErrors) { - if (clearExistingErrors || !form.$errors) { - form.$errors = []; - } - - var pushError = true; - for (var i = 0; i < form.$errors.length; i++) { - if (form.$errors[i] === errorMessage) { - pushError = false; - break; - } - } - - if (pushError) { - form.$errors.push(errorMessage); - } - - if (key && key !== '' && form[key] && form[key].$registerApiError) { - form[key].$registerApiError(); - } - }; - - _service.parseErrors = function (reason) { - var data = reason.data; - var defaultErrorMessage = 'An unexpected error has occurred.'; - var errors = []; - - if (!data || !angular.isObject(data)) { - errors.push(defaultErrorMessage); - return errors; - } - - if (data && data.ErrorModel) { - data = data.ErrorModel; - } - - if (!data.ValidationErrors) { - if (data.Message) { - errors.push(data.Message); - } - else { - errors.push(defaultErrorMessage); - } - } - - for (var key in data.ValidationErrors) { - if (!data.ValidationErrors.hasOwnProperty(key)) { - continue; - } - - for (var i = 0; i < data.ValidationErrors[key].length; i++) { - errors.push(data.ValidationErrors[key][i]); - } - } - - return errors; - }; - - return _service; - }); diff --git a/src/app/settings.js b/src/app/settings.js deleted file mode 100644 index 33c8cf1d54..0000000000 --- a/src/app/settings.js +++ /dev/null @@ -1,2 +0,0 @@ -angular.module("bit") -.constant("appSettings", {"apiUri":"/api","identityUri":"/identity","iconsUri":"https://icons.bitwarden.com","stripeKey":"pk_live_bpN0P37nMxrMQkcaHXtAybJk","braintreeKey":"production_qfbsv8kc_njj2zjtyngtjmbjd","selfHosted":false,"version":"1.27.0","environment":"Production"}); diff --git a/src/app/settings/account.component.html b/src/app/settings/account.component.html new file mode 100644 index 0000000000..46f06971aa --- /dev/null +++ b/src/app/settings/account.component.html @@ -0,0 +1,26 @@ + + +
+

{{'changeEmail' | i18n}}

+
+ +
+

{{'changeMasterPassword' | i18n}}

+
+ +
+

{{'dangerZone' | i18n}}

+
+
+
+

{{'dangerZoneDesc' | i18n}}

+ + + +
+
+ + + diff --git a/src/app/settings/account.component.ts b/src/app/settings/account.component.ts new file mode 100644 index 0000000000..b1138628d0 --- /dev/null +++ b/src/app/settings/account.component.ts @@ -0,0 +1,67 @@ +import { + Component, + ComponentFactoryResolver, + ViewChild, + ViewContainerRef, +} from '@angular/core'; + +import { ModalComponent } from '../modal.component'; +import { DeauthorizeSessionsComponent } from './deauthorize-sessions.component'; +import { DeleteAccountComponent } from './delete-account.component'; +import { PurgeVaultComponent } from './purge-vault.component'; + +@Component({ + selector: 'app-account', + templateUrl: 'account.component.html', +}) +export class AccountComponent { + @ViewChild('deauthorizeSessionsTemplate', { read: ViewContainerRef }) deauthModalRef: ViewContainerRef; + @ViewChild('purgeVaultTemplate', { read: ViewContainerRef }) purgeModalRef: ViewContainerRef; + @ViewChild('deleteAccountTemplate', { read: ViewContainerRef }) deleteModalRef: ViewContainerRef; + + private modal: ModalComponent = null; + + constructor(private componentFactoryResolver: ComponentFactoryResolver) { } + + deauthorizeSessions() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.deauthModalRef.createComponent(factory).instance; + this.modal.show(DeauthorizeSessionsComponent, this.deauthModalRef); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + purgeVault() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.purgeModalRef.createComponent(factory).instance; + this.modal.show(PurgeVaultComponent, this.purgeModalRef); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + deleteAccount() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.deleteModalRef.createComponent(factory).instance; + this.modal.show(DeleteAccountComponent, this.deleteModalRef); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } +} diff --git a/src/app/settings/adjust-payment.component.html b/src/app/settings/adjust-payment.component.html new file mode 100644 index 0000000000..03c45e7836 --- /dev/null +++ b/src/app/settings/adjust-payment.component.html @@ -0,0 +1,22 @@ + +

{{'contactSupportPaymentMethod' | i18n}}

+ + {{'contactSupport' | i18n}} + + +
+
+
+

{{(currentType != null ? 'changePaymentMethod' : 'addPaymentMethod') | i18n}}

+ + + +
+
diff --git a/src/app/settings/adjust-payment.component.ts b/src/app/settings/adjust-payment.component.ts new file mode 100644 index 0000000000..767600fb60 --- /dev/null +++ b/src/app/settings/adjust-payment.component.ts @@ -0,0 +1,64 @@ +import { + Component, + EventEmitter, + Input, + Output, + ViewChild, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { PaymentRequest } from 'jslib/models/request/paymentRequest'; + +import { PaymentMethodType } from 'jslib/enums/paymentMethodType'; + +import { PaymentComponent } from './payment.component'; + +@Component({ + selector: 'app-adjust-payment', + templateUrl: 'adjust-payment.component.html', +}) +export class AdjustPaymentComponent { + @ViewChild(PaymentComponent) paymentComponent: PaymentComponent; + + @Input() currentType?: PaymentMethodType; + @Input() user = true; + @Output() onAdjusted = new EventEmitter(); + @Output() onCanceled = new EventEmitter(); + + paymentMethodType = PaymentMethodType; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService) { } + + async submit() { + try { + const request = new PaymentRequest(); + this.formPromise = this.paymentComponent.createPaymentToken().then((token) => { + request.paymentToken = token; + if (this.user) { + return this.apiService.postAccountPayment(request); + } + }); + await this.formPromise; + this.analytics.eventTrack.next({ + action: this.currentType == null ? 'Added Payment Method' : 'Changed Payment Method', + }); + this.toasterService.popAsync('success', null, this.i18nService.t('updatedPaymentMethod')); + this.onAdjusted.emit(); + } catch { } + } + + cancel() { + this.onCanceled.emit(); + } + + get canChange() { + return this.currentType == null || this.currentType === PaymentMethodType.Card; + } +} diff --git a/src/app/settings/adjust-storage.component.html b/src/app/settings/adjust-storage.component.html new file mode 100644 index 0000000000..f4ed1f5fdb --- /dev/null +++ b/src/app/settings/adjust-storage.component.html @@ -0,0 +1,26 @@ +
+
+

{{(add ? 'addStorage' : 'removeStorage') | i18n}}

+
+
+ + +
+
+
+ {{'total' | i18n}}: {{storageAdjustment || 0}} GB × {{storageGbPrice | currency:'$'}} = {{adjustedStorageTotal + | currency:'$'}} /{{interval | i18n}} +
+ + + + {{(add ? 'storageAddNote' : 'storageRemoveNote') | i18n}} + +
+
diff --git a/src/app/settings/adjust-storage.component.ts b/src/app/settings/adjust-storage.component.ts new file mode 100644 index 0000000000..7ac6f6c337 --- /dev/null +++ b/src/app/settings/adjust-storage.component.ts @@ -0,0 +1,60 @@ +import { + Component, + EventEmitter, + Input, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { StorageRequest } from 'jslib/models/request/storageRequest'; + +@Component({ + selector: 'app-adjust-storage', + templateUrl: 'adjust-storage.component.html', +}) +export class AdjustStorageComponent { + @Input() storageGbPrice = 0; + @Input() add = true; + @Input() user = true; + @Input() interval = 'year'; + @Output() onAdjusted = new EventEmitter(); + @Output() onCanceled = new EventEmitter(); + + storageAdjustment = 0; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService) { } + + async submit() { + try { + const request = new StorageRequest(); + request.storageGbAdjustment = this.storageAdjustment; + if (!this.add) { + request.storageGbAdjustment *= -1; + } + + if (this.user) { + this.formPromise = this.apiService.postAccountStorage(request); + } + await this.formPromise; + this.analytics.eventTrack.next({ action: this.add ? 'Added Storage' : 'Removed Storage' }); + this.toasterService.popAsync('success', null, + this.i18nService.t('adjustedStorage', request.storageGbAdjustment.toString())); + this.onAdjusted.emit(this.storageAdjustment); + } catch { } + } + + cancel() { + this.onCanceled.emit(); + } + + get adjustedStorageTotal(): number { + return this.storageGbPrice * this.storageAdjustment; + } +} diff --git a/src/app/settings/change-email.component.html b/src/app/settings/change-email.component.html new file mode 100644 index 0000000000..b78fac20d8 --- /dev/null +++ b/src/app/settings/change-email.component.html @@ -0,0 +1,36 @@ +
+
+
+
+ + +
+
+ + +
+
+
+ +
+

{{'changeEmailDesc' | i18n : newEmail}}

+ {{'loggedOutWarning' | i18n}} +
+
+
+ + +
+
+
+
+ + +
diff --git a/src/app/settings/change-email.component.ts b/src/app/settings/change-email.component.ts new file mode 100644 index 0000000000..21f2fc460b --- /dev/null +++ b/src/app/settings/change-email.component.ts @@ -0,0 +1,75 @@ +import { + Component, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { MessagingService } from 'jslib/abstractions/messaging.service'; + +import { EmailRequest } from 'jslib/models/request/emailRequest'; +import { EmailTokenRequest } from 'jslib/models/request/emailTokenRequest'; + +@Component({ + selector: 'app-change-email', + templateUrl: 'change-email.component.html', +}) +export class ChangeEmailComponent { + masterPassword: string; + newEmail: string; + token: string; + tokenSent = false; + + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private cryptoService: CryptoService, private messagingService: MessagingService) { } + + async submit() { + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + this.toasterService.popAsync('error', null, this.i18nService.t('updateKey')); + return; + } + + this.newEmail = this.newEmail.toLowerCase(); + if (!this.tokenSent) { + const request = new EmailTokenRequest(); + request.newEmail = this.newEmail; + request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null); + try { + this.formPromise = this.apiService.postEmailToken(request); + await this.formPromise; + this.tokenSent = true; + } catch { } + } else { + const request = new EmailRequest(); + request.token = this.token; + request.newEmail = this.newEmail; + request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null); + const newKey = await this.cryptoService.makeKey(this.masterPassword, this.newEmail); + request.newMasterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, newKey); + const encKey = await this.cryptoService.getEncKey(); + const newEncKey = await this.cryptoService.encrypt(encKey.key, newKey); + request.key = newEncKey.encryptedString; + try { + this.formPromise = this.apiService.postEmail(request); + await this.formPromise; + this.reset(); + this.analytics.eventTrack.next({ action: 'Changed Email' }); + this.toasterService.popAsync('success', this.i18nService.t('emailChanged'), + this.i18nService.t('logBackIn')); + this.messagingService.send('logout'); + } catch { } + } + } + + reset() { + this.token = this.newEmail = this.masterPassword = null; + this.tokenSent = false; + } +} diff --git a/src/app/settings/change-password.component.html b/src/app/settings/change-password.component.html new file mode 100644 index 0000000000..29e14e9a92 --- /dev/null +++ b/src/app/settings/change-password.component.html @@ -0,0 +1,26 @@ +{{'loggedOutWarning' | i18n}} +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
diff --git a/src/app/settings/change-password.component.ts b/src/app/settings/change-password.component.ts new file mode 100644 index 0000000000..61c108cda2 --- /dev/null +++ b/src/app/settings/change-password.component.ts @@ -0,0 +1,71 @@ +import { + Component, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { MessagingService } from 'jslib/abstractions/messaging.service'; +import { UserService } from 'jslib/abstractions/user.service'; +import { PasswordRequest } from 'jslib/models/request/passwordRequest'; + +@Component({ + selector: 'app-change-password', + templateUrl: 'change-password.component.html', +}) +export class ChangePasswordComponent { + currentMasterPassword: string; + newMasterPassword: string; + confirmNewMasterPassword: string; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private cryptoService: CryptoService, private messagingService: MessagingService, + private userService: UserService) { } + + async submit() { + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + this.toasterService.popAsync('error', null, this.i18nService.t('updateKey')); + return; + } + + if (this.currentMasterPassword == null || this.currentMasterPassword === '' || + this.newMasterPassword == null || this.newMasterPassword === '') { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassRequired')); + return; + } + if (this.newMasterPassword.length < 8) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassLength')); + return; + } + if (this.newMasterPassword !== this.confirmNewMasterPassword) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassDoesntMatch')); + return; + } + + const request = new PasswordRequest(); + request.masterPasswordHash = await this.cryptoService.hashPassword(this.currentMasterPassword, null); + const email = await this.userService.getEmail(); + const newKey = await this.cryptoService.makeKey(this.newMasterPassword, email); + request.newMasterPasswordHash = await this.cryptoService.hashPassword(this.newMasterPassword, newKey); + const encKey = await this.cryptoService.getEncKey(); + const newEncKey = await this.cryptoService.encrypt(encKey.key, newKey); + request.key = newEncKey.encryptedString; + try { + this.formPromise = this.apiService.postPassword(request); + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Changed Password' }); + this.toasterService.popAsync('success', this.i18nService.t('masterPasswordChanged'), + this.i18nService.t('logBackIn')); + this.messagingService.send('logout'); + } catch { } + } +} diff --git a/src/app/settings/create-organization.component.html b/src/app/settings/create-organization.component.html new file mode 100644 index 0000000000..de76b539e4 --- /dev/null +++ b/src/app/settings/create-organization.component.html @@ -0,0 +1,180 @@ + +

{{'newOrganizationDesc' | i18n}}

+ +

{{'uploadLicenseFileOrg' | i18n}}

+
+
+ + + {{'licenseFileDesc' | i18n : 'bitwarden_organization_license.json'}} +
+ +
+
+
+

{{'generalInformation' | i18n}}

+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ + +
+
+

{{'chooseYourPlan' | i18n}}

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +

{{'users' | i18n}}

+
+
+ + + {{'userSeatsHowManyDesc' | i18n}} +
+
+
+

{{'addons' | i18n}}

+
+
+ + + {{'userSeatsAdditionalDesc' | i18n : plans[plan].baseSeats : (plans[plan].seatPrice | currency:'$')}} +
+
+
+
+ + + {{'additionalStorageDesc' | i18n : '1 GB' : (storageGb.price | currency:'$')}} +
+
+

{{'summary' | i18n}}

+
+ + +
+
+ + +
+
+
+ {{'total' | i18n}}: {{total | currency:'USD $'}} /{{interval | i18n}} +
+ {{'paymentChargedWithTrial' | i18n : (interval | i18n) }} +

{{'paymentInformation' | i18n}}

+ +
+
+ +
+
diff --git a/src/app/settings/create-organization.component.ts b/src/app/settings/create-organization.component.ts new file mode 100644 index 0000000000..aeac2ea956 --- /dev/null +++ b/src/app/settings/create-organization.component.ts @@ -0,0 +1,216 @@ +import { + Component, + EventEmitter, + Output, + ViewChild, +} from '@angular/core'; + +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; + +import { PaymentComponent } from './payment.component'; + +import { PlanType } from 'jslib/enums/planType'; +import { OrganizationCreateRequest } from 'jslib/models/request/organizationCreateRequest'; + +@Component({ + selector: 'app-create-organization', + templateUrl: 'create-organization.component.html', +}) +export class CreateOrganizationComponent { + @ViewChild(PaymentComponent) paymentComponent: PaymentComponent; + + selfHosted = false; + ownedBusiness = false; + storageGbPriceMonthly = 0.33; + additionalStorage = 0; + additionalSeats = 0; + plan = 'free'; + interval = 'year'; + name: string; + billingEmail: string; + businessName: string; + + storageGb: any = { + price: 0.33, + monthlyPrice: 0.50, + yearlyPrice: 4, + }; + + plans: any = { + free: { + basePrice: 0, + noAdditionalSeats: true, + noPayment: true, + }, + families: { + basePrice: 1, + annualBasePrice: 12, + baseSeats: 5, + noAdditionalSeats: true, + annualPlanType: PlanType.FamiliesAnnually, + }, + teams: { + basePrice: 5, + annualBasePrice: 60, + monthlyBasePrice: 8, + baseSeats: 5, + seatPrice: 2, + annualSeatPrice: 24, + monthlySeatPrice: 2.5, + monthPlanType: PlanType.TeamsMonthly, + annualPlanType: PlanType.TeamsAnnually, + }, + enterprise: { + seatPrice: 3, + annualSeatPrice: 36, + monthlySeatPrice: 4, + monthPlanType: PlanType.EnterpriseMonthly, + annualPlanType: PlanType.EnterpriseAnnually, + }, + }; + + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + platformUtilsService: PlatformUtilsService, private cryptoService: CryptoService, + private router: Router, private syncService: SyncService) { + this.selfHosted = platformUtilsService.isSelfHost(); + } + + async submit() { + let files: FileList = null; + if (this.selfHosted) { + const fileEl = document.getElementById('file') as HTMLInputElement; + files = fileEl.files; + if (files == null || files.length === 0) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('selectFile')); + return; + } + } + + let key: string = null; + let collectionCt: string = null; + + try { + this.formPromise = this.cryptoService.makeShareKey().then((shareKey) => { + key = shareKey[0].encryptedString; + return this.cryptoService.encrypt(this.i18nService.t('defaultCollection'), shareKey[1]); + }).then((collection) => { + collectionCt = collection.encryptedString; + if (this.selfHosted || this.plan === 'free') { + return null; + } else { + return this.paymentComponent.createPaymentToken(); + } + }).then((token: string) => { + if (this.selfHosted) { + const fd = new FormData(); + fd.append('license', files[0]); + fd.append('key', key); + fd.append('collectionName', collectionCt); + return this.apiService.postOrganizationLicense(fd); + } else { + const request = new OrganizationCreateRequest(); + request.key = key; + request.collectionName = collectionCt; + request.name = this.name; + request.billingEmail = this.billingEmail; + + if (this.plan === 'free') { + request.planType = PlanType.Free; + } else { + request.paymentToken = token; + request.businessName = this.ownedBusiness ? this.businessName : null; + request.additionalSeats = this.additionalSeats; + request.additionalStorageGb = this.additionalStorage; + request.country = this.paymentComponent.getCountry(); + if (this.interval === 'month') { + request.planType = this.plans[this.plan].monthPlanType; + } else { + request.planType = this.plans[this.plan].annualPlanType; + } + } + return this.apiService.postOrganization(request); + } + }).then((response) => { + return this.finalize(response.id); + }); + await this.formPromise; + } catch { } + } + + async finalize(orgId: string) { + await Promise.all([ + this.apiService.refreshIdentityToken(), + this.syncService.fullSync(true), + ]); + this.analytics.eventTrack.next({ action: 'Created Organization' }); + this.toasterService.popAsync('success', this.i18nService.t('organizationCreated'), + this.i18nService.t('organizationReadyToGo')); + this.router.navigate(['/organizations/' + orgId]); + } + + changedPlan() { + if (this.plans[this.plan].monthPlanType == null) { + this.interval = 'year'; + } + + if (this.plans[this.plan].noAdditionalSeats) { + this.additionalSeats = 0; + } else if (!this.additionalSeats && !this.plans[this.plan].baseSeats && + !this.plans[this.plan].noAdditionalSeats) { + this.additionalSeats = 1; + } + } + + changedOwnedBusiness() { + if (!this.ownedBusiness || this.plan === 'teams' || this.plan === 'enterprise') { + return; + } + this.plan = 'teams'; + } + + additionalStorageTotal(annual: boolean): number { + if (annual) { + return (this.additionalStorage || 0) * this.storageGb.yearlyPrice; + } else { + return (this.additionalStorage || 0) * this.storageGb.monthlyPrice; + } + } + + seatTotal(annual: boolean): number { + if (this.plans[this.plan].noAdditionalSeats) { + return 0; + } + + if (annual) { + return this.plans[this.plan].annualSeatPrice * (this.additionalSeats || 0); + } else { + return this.plans[this.plan].monthlySeatPrice * (this.additionalSeats || 0); + } + } + + baseTotal(annual: boolean): number { + if (annual) { + return (this.plans[this.plan].annualBasePrice || 0); + } else { + return (this.plans[this.plan].monthlyBasePrice || 0); + } + } + + get total(): number { + const annual = this.interval === 'year'; + return this.baseTotal(annual) + this.seatTotal(annual) + this.additionalStorageTotal(annual); + } +} diff --git a/src/app/settings/deauthorize-sessions.component.html b/src/app/settings/deauthorize-sessions.component.html new file mode 100644 index 0000000000..322c78a89b --- /dev/null +++ b/src/app/settings/deauthorize-sessions.component.html @@ -0,0 +1,26 @@ + diff --git a/src/app/settings/deauthorize-sessions.component.ts b/src/app/settings/deauthorize-sessions.component.ts new file mode 100644 index 0000000000..2a6ca26a86 --- /dev/null +++ b/src/app/settings/deauthorize-sessions.component.ts @@ -0,0 +1,43 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { MessagingService } from 'jslib/abstractions/messaging.service'; + +import { PasswordVerificationRequest } from 'jslib/models/request/passwordVerificationRequest'; + +@Component({ + selector: 'app-deauthorize-sessions', + templateUrl: 'deauthorize-sessions.component.html', +}) +export class DeauthorizeSessionsComponent { + masterPassword: string; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private cryptoService: CryptoService, private messagingService: MessagingService) { } + + async submit() { + if (this.masterPassword == null || this.masterPassword === '') { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassRequired')); + return; + } + + const request = new PasswordVerificationRequest(); + request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null); + try { + this.formPromise = this.apiService.postSecurityStamp(request); + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Deauthorized Sessions' }); + this.toasterService.popAsync('success', this.i18nService.t('sessionsDeauthorized'), + this.i18nService.t('logBackIn')); + this.messagingService.send('logout'); + } catch { } + } +} diff --git a/src/app/settings/delete-account.component.html b/src/app/settings/delete-account.component.html new file mode 100644 index 0000000000..02c4049e17 --- /dev/null +++ b/src/app/settings/delete-account.component.html @@ -0,0 +1,26 @@ + diff --git a/src/app/settings/delete-account.component.ts b/src/app/settings/delete-account.component.ts new file mode 100644 index 0000000000..5096b801af --- /dev/null +++ b/src/app/settings/delete-account.component.ts @@ -0,0 +1,43 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { MessagingService } from 'jslib/abstractions/messaging.service'; + +import { PasswordVerificationRequest } from 'jslib/models/request/passwordVerificationRequest'; + +@Component({ + selector: 'app-delete-account', + templateUrl: 'delete-account.component.html', +}) +export class DeleteAccountComponent { + masterPassword: string; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private cryptoService: CryptoService, private messagingService: MessagingService) { } + + async submit() { + if (this.masterPassword == null || this.masterPassword === '') { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassRequired')); + return; + } + + const request = new PasswordVerificationRequest(); + request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null); + try { + this.formPromise = this.apiService.postDeleteAccount(request); + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Deleted Account' }); + this.toasterService.popAsync('success', this.i18nService.t('accountDeleted'), + this.i18nService.t('accountDeletedDesc')); + this.messagingService.send('logout'); + } catch { } + } +} diff --git a/src/app/settings/domain-rules.component.html b/src/app/settings/domain-rules.component.html new file mode 100644 index 0000000000..3f0835c24b --- /dev/null +++ b/src/app/settings/domain-rules.component.html @@ -0,0 +1,65 @@ + +

{{'domainRulesDesc' | i18n}}

+
+

{{'customEqDomains' | i18n}}

+

+ +

+ +
+
+ + +
+ +
+ + {{'newCustomDomainDesc' | i18n}} +
+ +

{{'globalEqDomains' | i18n}}

+

+ +

+ + + + + + + +
{{d.domains}} + +
+ +
diff --git a/src/app/settings/domain-rules.component.ts b/src/app/settings/domain-rules.component.ts new file mode 100644 index 0000000000..5dd76a15a2 --- /dev/null +++ b/src/app/settings/domain-rules.component.ts @@ -0,0 +1,85 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { UpdateDomainsRequest } from 'jslib/models/request/updateDomainsRequest'; + +@Component({ + selector: 'app-domain-rules', + templateUrl: 'domain-rules.component.html', +}) +export class DomainRulesComponent implements OnInit { + loading = true; + custom: string[] = []; + global: any[] = []; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService) { } + + async ngOnInit() { + const response = await this.apiService.getSettingsDomains(); + this.loading = false; + if (response.equivalentDomains != null) { + this.custom = response.equivalentDomains.map((d) => d.join(', ')); + } + if (response.globalEquivalentDomains != null) { + this.global = response.globalEquivalentDomains.map((d) => { + return { + domains: d.domains.join(', '), + excluded: d.excluded, + key: d.type, + }; + }); + } + } + + toggleExcluded(globalDomain: any) { + globalDomain.excluded = !globalDomain.excluded; + } + + customize(globalDomain: any) { + globalDomain.excluded = true; + this.custom.push(globalDomain.domains); + } + + remove(index: number) { + this.custom.splice(index, 1); + } + + add() { + this.custom.push(''); + } + + async submit() { + const request = new UpdateDomainsRequest(); + request.excludedGlobalEquivalentDomains = this.global.filter((d) => d.excluded) + .map((d) => d.key); + if (request.excludedGlobalEquivalentDomains.length === 0) { + request.excludedGlobalEquivalentDomains = null; + } + request.equivalentDomains = this.custom.filter((d) => d != null && d.trim() !== '') + .map((d) => d.split(' ').join('').split(',')); + if (request.equivalentDomains.length === 0) { + request.equivalentDomains = null; + } + + try { + this.formPromise = this.apiService.putSettingsDomains(request); + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Saved Equivalent Domains' }); + this.toasterService.popAsync('success', null, this.i18nService.t('domainsUpdated')); + } catch { } + } + + indexTrackBy(index: number, obj: any): any { + return index; + } +} diff --git a/src/app/settings/options.component.html b/src/app/settings/options.component.html new file mode 100644 index 0000000000..9297146bbe --- /dev/null +++ b/src/app/settings/options.component.html @@ -0,0 +1,29 @@ + +

{{'optionsDesc' | i18n}}

+
+
+
+
+ + + {{'languageDesc' | i18n}} +
+
+
+
+
+ + +
+ {{'disableIconsDesc' | i18n}} +
+ +
diff --git a/src/app/settings/options.component.ts b/src/app/settings/options.component.ts new file mode 100644 index 0000000000..c42ce620fd --- /dev/null +++ b/src/app/settings/options.component.ts @@ -0,0 +1,51 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { StateService } from 'jslib/abstractions/state.service'; +import { StorageService } from 'jslib/abstractions/storage.service'; + +import { ConstantsService } from 'jslib/services/constants.service'; + +@Component({ + selector: 'app-options', + templateUrl: 'options.component.html', +}) +export class OptionsComponent implements OnInit { + disableIcons: boolean; + locale: string; + localeOptions: any[]; + + private startingLocale: string; + + constructor(private storageService: StorageService, private stateService: StateService, + private analytics: Angulartics2, private i18nService: I18nService, + private toasterService: ToasterService) { + this.localeOptions = [{ name: i18nService.t('default'), value: null }]; + i18nService.supportedTranslationLocales.forEach((locale) => { + this.localeOptions.push({ name: locale, value: locale }); + }); + } + + async ngOnInit() { + this.disableIcons = await this.storageService.get(ConstantsService.disableFaviconKey); + this.locale = this.startingLocale = await this.storageService.get(ConstantsService.localeKey); + } + + async submit() { + await this.storageService.save(ConstantsService.disableFaviconKey, this.disableIcons); + await this.stateService.save(ConstantsService.disableFaviconKey, this.disableIcons); + await this.storageService.save(ConstantsService.localeKey, this.locale); + this.analytics.eventTrack.next({ action: 'Saved Options' }); + if (this.locale !== this.startingLocale) { + window.location.reload(); + } else { + this.toasterService.popAsync('success', null, this.i18nService.t('optionsUpdated')); + } + } +} diff --git a/src/app/settings/organizations.component.html b/src/app/settings/organizations.component.html new file mode 100644 index 0000000000..fddd4c1650 --- /dev/null +++ b/src/app/settings/organizations.component.html @@ -0,0 +1,62 @@ + +

+ +

+ + +

{{'noOrganizationsList' | i18n}}

+
+ + + {{'newOrganization' | i18n}} + +
+ + + + +

{{'noOrganizationsList' | i18n}}

+ + + + + + + + +
+ + + {{o.name}} + + +
+
+
diff --git a/src/app/settings/organizations.component.ts b/src/app/settings/organizations.component.ts new file mode 100644 index 0000000000..a9087d522b --- /dev/null +++ b/src/app/settings/organizations.component.ts @@ -0,0 +1,65 @@ +import { + Component, + Input, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { Organization } from 'jslib/models/domain/organization'; + +import { Utils } from 'jslib/misc/utils'; + +@Component({ + selector: 'app-organizations', + templateUrl: 'organizations.component.html', +}) +export class OrganizationsComponent implements OnInit { + @Input() vault = false; + + organizations: Organization[]; + loaded: boolean = false; + actionPromise: Promise; + + constructor(private userService: UserService, private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, private apiService: ApiService, + private analytics: Angulartics2, private toasterService: ToasterService, + private syncService: SyncService) { } + + async ngOnInit() { + await this.load(); + } + + async load() { + const orgs = await this.userService.getAllOrganizations(); + orgs.sort(Utils.getSortFunction(this.i18nService, 'name')); + this.organizations = orgs; + this.loaded = true; + } + + async leave(org: Organization) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t('leaveOrganizationConfirmation'), org.name, + this.i18nService.t('yes'), this.i18nService.t('no'), 'warning'); + if (!confirmed) { + return false; + } + + try { + this.actionPromise = this.apiService.postLeaveOrganization(org.id).then(() => { + return this.syncService.fullSync(true); + }); + await this.actionPromise; + this.analytics.eventTrack.next({ action: 'Left Organization' }); + this.toasterService.popAsync('success', null, this.i18nService.t('leftOrganization')); + await this.load(); + } catch { } + } +} diff --git a/src/app/settings/payment.component.html b/src/app/settings/payment.component.html new file mode 100644 index 0000000000..58e1611b82 --- /dev/null +++ b/src/app/settings/payment.component.html @@ -0,0 +1,311 @@ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+ {{'paypalClickSubmit' | i18n}} +
+
diff --git a/src/app/settings/payment.component.ts b/src/app/settings/payment.component.ts new file mode 100644 index 0000000000..7ca2dc64fb --- /dev/null +++ b/src/app/settings/payment.component.ts @@ -0,0 +1,147 @@ +import { + Component, + Input, + OnInit, +} from '@angular/core'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +const Keys = { + stripeTest: 'pk_test_KPoCfZXu7mznb9uSCPZ2JpTD', + stripeLive: 'pk_live_bpN0P37nMxrMQkcaHXtAybJk', + btSandbox: 'sandbox_r72q8jq6_9pnxkwm75f87sdc2', + btProduction: 'production_qfbsv8kc_njj2zjtyngtjmbjd', +}; + +@Component({ + selector: 'app-payment', + templateUrl: 'payment.component.html', +}) +export class PaymentComponent implements OnInit { + @Input() showOptions = true; + + method = 'card'; + card: any = { + number: null, + exp_month: null, + exp_year: null, + address_country: '', + address_zip: null, + }; + cardExpMonthOptions: any[]; + cardExpYearOptions: any[]; + + private stripeScript: HTMLScriptElement; + private btScript: HTMLScriptElement; + private btInstance: any = null; + + constructor(i18nService: I18nService, private platformUtilsService: PlatformUtilsService) { + this.stripeScript = window.document.createElement('script'); + this.stripeScript.src = 'https://js.stripe.com/v2/'; + this.stripeScript.async = true; + this.stripeScript.onload = () => { + (window as any).Stripe.setPublishableKey( + this.platformUtilsService.isDev() ? Keys.stripeTest : Keys.stripeLive); + }; + this.btScript = window.document.createElement('script'); + this.btScript.src = 'https://js.braintreegateway.com/web/dropin/1.4.0/js/dropin.min.js'; + this.btScript.async = true; + + this.cardExpMonthOptions = [ + { name: '-- ' + i18nService.t('select') + ' --', value: null }, + { name: '01 - ' + i18nService.t('january'), value: '01' }, + { name: '02 - ' + i18nService.t('february'), value: '02' }, + { name: '03 - ' + i18nService.t('march'), value: '03' }, + { name: '04 - ' + i18nService.t('april'), value: '04' }, + { name: '05 - ' + i18nService.t('may'), value: '05' }, + { name: '06 - ' + i18nService.t('june'), value: '06' }, + { name: '07 - ' + i18nService.t('july'), value: '07' }, + { name: '08 - ' + i18nService.t('august'), value: '08' }, + { name: '09 - ' + i18nService.t('september'), value: '09' }, + { name: '10 - ' + i18nService.t('october'), value: '10' }, + { name: '11 - ' + i18nService.t('november'), value: '11' }, + { name: '12 - ' + i18nService.t('december'), value: '12' }, + ]; + + this.cardExpYearOptions = [ + { name: '-- ' + i18nService.t('select') + ' --', value: null }, + ]; + const year = (new Date()).getFullYear(); + for (let i = year; i < (year + 10); i++) { + this.cardExpYearOptions.push({ name: i.toString(), value: i.toString().slice(-2) }); + } + } + + ngOnInit() { + window.document.head.appendChild(this.stripeScript); + window.document.head.appendChild(this.btScript); + } + + ngOnDestroy() { + window.document.head.removeChild(this.stripeScript); + window.document.head.removeChild(this.btScript); + Array.from(window.document.querySelectorAll('iframe')).forEach((el) => { + if (el.src != null && el.src.indexOf('stripe') > -1) { + window.document.body.removeChild(el); + } + }); + } + + changeMethod() { + if (this.method !== 'paypal') { + this.btInstance = null; + return; + } + + window.setTimeout(() => { + (window as any).braintree.dropin.create({ + authorization: this.platformUtilsService.isDev() ? Keys.btSandbox : Keys.btProduction, + container: '#bt-dropin-container', + paymentOptionPriority: ['paypal'], + paypal: { + flow: 'vault', + buttonStyle: { + label: 'pay', + size: 'medium', + shape: 'pill', + color: 'blue', + }, + }, + }, (createErr: any, instance: any) => { + if (createErr != null) { + // tslint:disable-next-line + console.error(createErr); + return; + } + this.btInstance = instance; + }); + }, 250); + } + + createPaymentToken(): Promise { + return new Promise((resolve, reject) => { + if (this.method === 'paypal') { + this.btInstance.requestPaymentMethod().then((payload: any) => { + resolve(payload.nonce); + }).catch((err: any) => { + reject(err.message); + }); + } else { + (window as any).Stripe.card.createToken(this.card, (status: number, response: any) => { + if (status === 200 && response.id != null) { + resolve(response.id); + } else if (response.error != null) { + reject(response.error.message); + } else { + reject(); + } + }); + } + }); + } + + getCountry(): string { + return this.card.address_country; + } +} diff --git a/src/app/settings/premium.component.html b/src/app/settings/premium.component.html new file mode 100644 index 0000000000..d436234929 --- /dev/null +++ b/src/app/settings/premium.component.html @@ -0,0 +1,73 @@ + + +

{{'premiumSignUpAndGet' | i18n}}

+
    +
  • + + {{'premiumSignUpStorage' | i18n}} +
  • +
  • + + {{'premiumSignUpTwoStep' | i18n}} +
  • +
  • + + {{'premiumSignUpTotp' | i18n}} +
  • +
  • + + {{'premiumSignUpSupport' | i18n}} +
  • +
  • + + {{'premiumSignUpFuture' | i18n}} +
  • +
+

{{'premiumPrice' | i18n : (premiumPrice | currency:'$')}}

+ + {{'purchasePremium' | i18n}} + +
+ +

{{'uploadLicenseFilePremium' | i18n}}

+
+
+ + + {{'licenseFileDesc' | i18n : 'bitwarden_premium_license.json'}} +
+ +
+
+
+

{{'addons' | i18n}}

+
+
+ + + {{'additionalStorageDesc' | i18n : '1 GB' : (storageGbPrice | currency:'$')}} +
+
+

{{'summary' | i18n}}

+ {{'premiumMembership' | i18n}}: {{premiumPrice | currency:'$'}} +
{{'additionalStorageGb' | i18n}}: {{additionalStorage || 0}} GB × {{storageGbPrice | currency:'$'}} = {{additionalStorageTotal + | currency:'$'}} +
+
+ {{'total' | i18n}}: {{total | currency:'USD $'}} /{{'year' | i18n}} +
+ {{'paymentChargedAnnually' | i18n}} +

{{'paymentInformation' | i18n}}

+ + +
diff --git a/src/app/settings/premium.component.ts b/src/app/settings/premium.component.ts new file mode 100644 index 0000000000..5e7975d23e --- /dev/null +++ b/src/app/settings/premium.component.ts @@ -0,0 +1,101 @@ +import { + Component, + OnInit, + ViewChild, +} from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { MessagingService } from 'jslib/abstractions/messaging.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; +import { TokenService } from 'jslib/abstractions/token.service'; + +import { PaymentComponent } from './payment.component'; + +@Component({ + selector: 'app-premium', + templateUrl: 'premium.component.html', +}) +export class PremiumComponent implements OnInit { + @ViewChild(PaymentComponent) paymentComponent: PaymentComponent; + + selfHosted = false; + premiumPrice = 10; + storageGbPrice = 4; + additionalStorage = 0; + + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + platformUtilsService: PlatformUtilsService, private tokenService: TokenService, + private router: Router, private messagingService: MessagingService, + private syncService: SyncService) { + this.selfHosted = platformUtilsService.isSelfHost(); + } + + async ngOnInit() { + const premium = await this.tokenService.getPremium(); + if (premium) { + this.router.navigate(['/settings/billing']); + return; + } + } + + async submit() { + let files: FileList = null; + if (this.selfHosted) { + const fileEl = document.getElementById('file') as HTMLInputElement; + files = fileEl.files; + if (files == null || files.length === 0) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('selectFile')); + return; + } + } + + try { + if (this.selfHosted) { + const fd = new FormData(); + fd.append('license', files[0]); + this.formPromise = this.apiService.postAccountLicense(fd).then(() => { + return this.finalizePremium(); + }); + } else { + this.formPromise = this.paymentComponent.createPaymentToken().then((token) => { + const fd = new FormData(); + fd.append('paymentToken', token); + fd.append('additionalStorageGb', (this.additionalStorage || 0).toString()); + return this.apiService.postPremium(fd); + }).then(() => { + return this.finalizePremium(); + }); + } + await this.formPromise; + } catch { } + } + + async finalizePremium() { + await Promise.all([ + this.apiService.refreshIdentityToken(), + this.syncService.fullSync(true), + ]); + this.analytics.eventTrack.next({ action: 'Signed Up Premium' }); + this.toasterService.popAsync('success', null, this.i18nService.t('premiumUpdated')); + this.messagingService.send('purchasedPremium'); + this.router.navigate(['/settings/billing']); + } + + get additionalStorageTotal(): number { + return this.storageGbPrice * this.additionalStorage; + } + + get total(): number { + return this.additionalStorageTotal + this.premiumPrice; + } +} diff --git a/src/app/settings/profile.component.html b/src/app/settings/profile.component.html new file mode 100644 index 0000000000..750c00d7bc --- /dev/null +++ b/src/app/settings/profile.component.html @@ -0,0 +1,28 @@ +
+ +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+ +
diff --git a/src/app/settings/profile.component.ts b/src/app/settings/profile.component.ts new file mode 100644 index 0000000000..fa2a2b55a5 --- /dev/null +++ b/src/app/settings/profile.component.ts @@ -0,0 +1,43 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { UpdateProfileRequest } from 'jslib/models/request/updateProfileRequest'; + +import { ProfileResponse } from 'jslib/models/response/profileResponse'; + +@Component({ + selector: 'app-profile', + templateUrl: 'profile.component.html', +}) +export class ProfileComponent implements OnInit { + loading = true; + profile: ProfileResponse; + + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService) { } + + async ngOnInit() { + this.profile = await this.apiService.getProfile(); + this.loading = false; + } + + async submit() { + try { + const request = new UpdateProfileRequest(this.profile.name, this.profile.masterPasswordHint); + this.formPromise = this.apiService.putProfile(request); + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Updated Profile' }); + this.toasterService.popAsync('success', null, this.i18nService.t('accountUpdated')); + } catch { } + } +} diff --git a/src/app/settings/purge-vault.component.html b/src/app/settings/purge-vault.component.html new file mode 100644 index 0000000000..97499badfc --- /dev/null +++ b/src/app/settings/purge-vault.component.html @@ -0,0 +1,26 @@ + diff --git a/src/app/settings/purge-vault.component.ts b/src/app/settings/purge-vault.component.ts new file mode 100644 index 0000000000..d1f939b14a --- /dev/null +++ b/src/app/settings/purge-vault.component.ts @@ -0,0 +1,42 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { PasswordVerificationRequest } from 'jslib/models/request/passwordVerificationRequest'; + +@Component({ + selector: 'app-purge-vault', + templateUrl: 'purge-vault.component.html', +}) +export class PurgeVaultComponent { + masterPassword: string; + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private cryptoService: CryptoService, private router: Router) { } + + async submit() { + if (this.masterPassword == null || this.masterPassword === '') { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassRequired')); + return; + } + + const request = new PasswordVerificationRequest(); + request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null); + try { + this.formPromise = this.apiService.postPurgeCiphers(request); + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Purged Vault' }); + this.toasterService.popAsync('success', null, this.i18nService.t('vaultPurged')); + this.router.navigate(['vault']); + } catch { } + } +} diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html new file mode 100644 index 0000000000..03c1943d84 --- /dev/null +++ b/src/app/settings/settings.component.html @@ -0,0 +1,35 @@ + diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts new file mode 100644 index 0000000000..68b398f78b --- /dev/null +++ b/src/app/settings/settings.component.ts @@ -0,0 +1,46 @@ +import { + Component, + NgZone, + OnDestroy, + OnInit, +} from '@angular/core'; + +import { TokenService } from 'jslib/abstractions/token.service'; + +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + +const BroadcasterSubscriptionId = 'SettingsComponent'; + +@Component({ + selector: 'app-settings', + templateUrl: 'settings.component.html', +}) +export class SettingsComponent implements OnInit, OnDestroy { + premium: boolean; + + constructor(private tokenService: TokenService, private broadcasterService: BroadcasterService, + private ngZone: NgZone) { } + + async ngOnInit() { + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case 'purchasedPremium': + await this.load(); + break; + default: + } + }); + }); + + await this.load(); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async load() { + this.premium = await this.tokenService.getPremium(); + } +} diff --git a/src/app/settings/settingsAddEditEquivalentDomainController.js b/src/app/settings/settingsAddEditEquivalentDomainController.js deleted file mode 100644 index 3611eed599..0000000000 --- a/src/app/settings/settingsAddEditEquivalentDomainController.js +++ /dev/null @@ -1,19 +0,0 @@ -angular - .module('bit.vault') - - .controller('settingsAddEditEquivalentDomainController', function ($scope, $uibModalInstance, $analytics, - domainIndex, domains) { - $analytics.eventTrack('settingsAddEditEquivalentDomainController', { category: 'Modal' }); - - $scope.domains = domains; - $scope.index = domainIndex; - - $scope.submit = function (form) { - $analytics.eventTrack((domainIndex ? 'Edited' : 'Added') + ' Equivalent Domain'); - $uibModalInstance.close({ domains: $scope.domains, index: domainIndex }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - }); diff --git a/src/app/settings/settingsBillingAdjustStorageController.js b/src/app/settings/settingsBillingAdjustStorageController.js deleted file mode 100644 index ceb1709c50..0000000000 --- a/src/app/settings/settingsBillingAdjustStorageController.js +++ /dev/null @@ -1,37 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsBillingAdjustStorageController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, add) { - $analytics.eventTrack('settingsBillingAdjustStorageController', { category: 'Modal' }); - $scope.add = add; - $scope.storageAdjustment = 0; - - $scope.submit = function () { - var request = { - storageGbAdjustment: $scope.storageAdjustment - }; - - if (!add) { - request.storageGbAdjustment *= -1; - } - - $scope.submitPromise = apiService.accounts.putStorage(null, request) - .$promise.then(function (response) { - if (add) { - $analytics.eventTrack('Added Storage'); - toastr.success('You have added ' + $scope.storageAdjustment + ' GB.'); - } - else { - $analytics.eventTrack('Removed Storage'); - toastr.success('You have removed ' + $scope.storageAdjustment + ' GB.'); - } - - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsBillingChangePaymentController.js b/src/app/settings/settingsBillingChangePaymentController.js deleted file mode 100644 index b1a50aac55..0000000000 --- a/src/app/settings/settingsBillingChangePaymentController.js +++ /dev/null @@ -1,101 +0,0 @@ -angular - .module('bit.organization') - - .controller('settingsBillingChangePaymentController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, existingPaymentMethod, appSettings, $timeout - // @if !selfHosted - /* jshint ignore:start */ - , stripe - /* jshint ignore:end */ - // @endif - ) { - $analytics.eventTrack('settingsBillingChangePaymentController', { category: 'Modal' }); - $scope.existingPaymentMethod = existingPaymentMethod; - $scope.paymentMethod = 'card'; - $scope.dropinLoaded = false; - $scope.showPaymentOptions = false; - $scope.hideBank = true; - $scope.card = {}; - var btInstance = null; - - $scope.changePaymentMethod = function (val) { - $scope.paymentMethod = val; - if ($scope.paymentMethod !== 'paypal') { - return; - } - - braintree.dropin.create({ - authorization: appSettings.braintreeKey, - container: '#bt-dropin-container', - paymentOptionPriority: ['paypal'], - paypal: { - flow: 'vault', - buttonStyle: { - label: 'pay', - size: 'medium', - shape: 'pill', - color: 'blue' - } - } - }, function (createErr, instance) { - if (createErr) { - console.error(createErr); - return; - } - - btInstance = instance; - $timeout(function () { - $scope.dropinLoaded = true; - }); - }); - }; - - $scope.submit = function () { - $scope.submitPromise = getPaymentToken($scope.card).then(function (token) { - if (!token) { - throw 'No payment token.'; - } - - var request = { - paymentToken: token - }; - - return apiService.accounts.putPayment(null, request).$promise; - }, function (err) { - throw err; - }).then(function (response) { - $scope.card = null; - if (existingPaymentMethod) { - $analytics.eventTrack('Changed Payment Method'); - toastr.success('You have changed your payment method.'); - } - else { - $analytics.eventTrack('Added Payment Method'); - toastr.success('You have added a payment method.'); - } - - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - function getPaymentToken(card) { - if ($scope.paymentMethod === 'paypal') { - return btInstance.requestPaymentMethod().then(function (payload) { - return payload.nonce; - }).catch(function (err) { - throw err.message; - }); - } - else { - return stripe.card.createToken(card).then(function (response) { - return response.id; - }).catch(function (err) { - throw err.message; - }); - } - } - }); diff --git a/src/app/settings/settingsBillingController.js b/src/app/settings/settingsBillingController.js deleted file mode 100644 index faf498a7fd..0000000000 --- a/src/app/settings/settingsBillingController.js +++ /dev/null @@ -1,225 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsBillingController', function ($scope, apiService, authService, $state, $uibModal, toastr, $analytics, - appSettings) { - $scope.selfHosted = appSettings.selfHosted; - $scope.charges = []; - $scope.paymentSource = null; - $scope.subscription = null; - $scope.loading = true; - var license = null; - $scope.expiration = null; - - $scope.$on('$viewContentLoaded', function () { - load(); - }); - - $scope.changePayment = function () { - if ($scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsBillingChangePayment.html', - controller: 'settingsBillingChangePaymentController', - resolve: { - existingPaymentMethod: function () { - return $scope.paymentSource ? $scope.paymentSource.description : null; - } - } - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.adjustStorage = function (add) { - if ($scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsBillingAdjustStorage.html', - controller: 'settingsBillingAdjustStorageController', - resolve: { - add: function () { - return add; - } - } - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.cancel = function () { - if ($scope.selfHosted) { - return; - } - - if (!confirm('Are you sure you want to cancel? You will lose access to all premium features at the end ' + - 'of this billing cycle.')) { - return; - } - - apiService.accounts.putCancelPremium({}, {}) - .$promise.then(function (response) { - $analytics.eventTrack('Canceled Premium'); - toastr.success('Premium subscription has been canceled.'); - load(); - }); - }; - - $scope.reinstate = function () { - if ($scope.selfHosted) { - return; - } - - if (!confirm('Are you sure you want to remove the cancellation request and reinstate your premium membership?')) { - return; - } - - apiService.accounts.putReinstatePremium({}, {}) - .$promise.then(function (response) { - $analytics.eventTrack('Reinstated Premium'); - toastr.success('Premium cancellation request has been removed.'); - load(); - }); - }; - - $scope.updateLicense = function () { - if (!$scope.selfHosted) { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsBillingUpdateLicense.html', - controller: 'settingsBillingUpdateLicenseController' - }); - - modal.result.then(function () { - load(); - }); - }; - - $scope.license = function () { - if ($scope.selfHosted) { - return; - } - - var licenseString = JSON.stringify(license, null, 2); - var licenseBlob = new Blob([licenseString]); - - // IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx - if (window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveBlob(licenseBlob, 'bitwarden_premium_license.json'); - } - else { - var a = window.document.createElement('a'); - a.href = window.URL.createObjectURL(licenseBlob, { type: 'text/plain' }); - a.download = 'bitwarden_premium_license.json'; - document.body.appendChild(a); - // IE: "Access is denied". - // ref: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access - a.click(); - document.body.removeChild(a); - } - }; - - function load() { - authService.getUserProfile().then(function (profile) { - $scope.premium = profile.premium; - if (!profile.premium) { - return null; - } - - return apiService.accounts.getBilling({}).$promise; - }).then(function (billing) { - if (!billing) { - return $state.go('backend.user.settingsPremium'); - } - - var i = 0; - $scope.expiration = billing.Expiration; - license = billing.License; - - $scope.storage = null; - if (billing && billing.MaxStorageGb) { - $scope.storage = { - currentGb: billing.StorageGb || 0, - maxGb: billing.MaxStorageGb, - currentName: billing.StorageName || '0 GB' - }; - - $scope.storage.percentage = +(100 * ($scope.storage.currentGb / $scope.storage.maxGb)).toFixed(2); - } - - $scope.subscription = null; - if (billing && billing.Subscription) { - $scope.subscription = { - trialEndDate: billing.Subscription.TrialEndDate, - cancelledDate: billing.Subscription.CancelledDate, - status: billing.Subscription.Status, - cancelled: billing.Subscription.Cancelled, - markedForCancel: !billing.Subscription.Cancelled && billing.Subscription.CancelAtEndDate - }; - } - - $scope.nextInvoice = null; - if (billing && billing.UpcomingInvoice) { - $scope.nextInvoice = { - date: billing.UpcomingInvoice.Date, - amount: billing.UpcomingInvoice.Amount - }; - } - - if (billing && billing.Subscription && billing.Subscription.Items) { - $scope.subscription.items = []; - for (i = 0; i < billing.Subscription.Items.length; i++) { - $scope.subscription.items.push({ - amount: billing.Subscription.Items[i].Amount, - name: billing.Subscription.Items[i].Name, - interval: billing.Subscription.Items[i].Interval, - qty: billing.Subscription.Items[i].Quantity - }); - } - } - - $scope.paymentSource = null; - if (billing && billing.PaymentSource) { - $scope.paymentSource = { - type: billing.PaymentSource.Type, - description: billing.PaymentSource.Description, - cardBrand: billing.PaymentSource.CardBrand - }; - } - - var charges = []; - if (billing && billing.Charges) { - for (i = 0; i < billing.Charges.length; i++) { - charges.push({ - date: billing.Charges[i].CreatedDate, - paymentSource: billing.Charges[i].PaymentSource ? - billing.Charges[i].PaymentSource.Description : '-', - amount: billing.Charges[i].Amount, - status: billing.Charges[i].Status, - failureMessage: billing.Charges[i].FailureMessage, - refunded: billing.Charges[i].Refunded, - partiallyRefunded: billing.Charges[i].PartiallyRefunded, - refundedAmount: billing.Charges[i].RefundedAmount, - invoiceId: billing.Charges[i].InvoiceId - }); - } - } - $scope.charges = charges; - - $scope.loading = false; - }); - } - }); diff --git a/src/app/settings/settingsBillingUpdateLicenseController.js b/src/app/settings/settingsBillingUpdateLicenseController.js deleted file mode 100644 index 3b5d7fa550..0000000000 --- a/src/app/settings/settingsBillingUpdateLicenseController.js +++ /dev/null @@ -1,30 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsBillingUpdateLicenseController', function ($scope, $state, $uibModalInstance, apiService, - $analytics, toastr, validationService) { - $analytics.eventTrack('settingsBillingUpdateLicenseController', { category: 'Modal' }); - - $scope.submit = function (form) { - var fileEl = document.getElementById('file'); - var files = fileEl.files; - if (!files || !files.length) { - validationService.addError(form, 'file', 'Select a license file.', true); - return; - } - - var fd = new FormData(); - fd.append('license', files[0]); - - $scope.submitPromise = apiService.accounts.putLicense(fd) - .$promise.then(function (response) { - $analytics.eventTrack('Updated License'); - toastr.success('You have updated your license.'); - $uibModalInstance.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsChangeEmailController.js b/src/app/settings/settingsChangeEmailController.js deleted file mode 100644 index 04cc59087c..0000000000 --- a/src/app/settings/settingsChangeEmailController.js +++ /dev/null @@ -1,63 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsChangeEmailController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics, validationService) { - $analytics.eventTrack('settingsChangeEmailController', { category: 'Modal' }); - - var _masterPasswordHash, - _masterPassword, - _newEmail; - - $scope.token = function (model, form) { - var encKey = cryptoService.getEncKey(); - if (!encKey) { - validationService.addError(form, null, - 'You cannot change your email until you update your encryption key.', true); - return; - } - - _masterPassword = model.masterPassword; - _newEmail = model.newEmail.toLowerCase(); - - $scope.tokenPromise = cryptoService.hashPassword(_masterPassword).then(function (hash) { - _masterPasswordHash = hash; - - var request = { - newEmail: _newEmail, - masterPasswordHash: _masterPasswordHash - }; - - return apiService.accounts.emailToken(request, function () { - $scope.tokenSent = true; - }).$promise; - }); - }; - - $scope.confirm = function (model) { - $scope.confirmPromise = cryptoService.makeKeyAndHash(_newEmail, _masterPassword).then(function (result) { - var encKey = cryptoService.getEncKey(); - var newEncKey = cryptoService.encrypt(encKey.key, result.key, 'raw'); - var request = { - token: model.token, - newEmail: _newEmail, - masterPasswordHash: _masterPasswordHash, - newMasterPasswordHash: result.hash, - key: newEncKey - }; - - return apiService.accounts.email(request).$promise; - }).then(function () { - $uibModalInstance.dismiss('cancel'); - authService.logOut(); - $analytics.eventTrack('Changed Email'); - return $state.go('frontend.login.info'); - }).then(function () { - toastr.success('Please log back in.', 'Email Changed'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsChangePasswordController.js b/src/app/settings/settingsChangePasswordController.js deleted file mode 100644 index 247a99fa85..0000000000 --- a/src/app/settings/settingsChangePasswordController.js +++ /dev/null @@ -1,63 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsChangePasswordController', function ($scope, $state, apiService, $uibModalInstance, - cryptoService, authService, validationService, toastr, $analytics) { - $analytics.eventTrack('settingsChangePasswordController', { category: 'Modal' }); - - $scope.save = function (model, form) { - var error = false; - - var encKey = cryptoService.getEncKey(); - if (!encKey) { - validationService.addError(form, null, - 'You cannot change your master password until you update your encryption key.', true); - error = true; - } - - if ($scope.model.newMasterPassword.length < 8) { - validationService.addError(form, 'NewMasterPasswordHash', - 'Master password must be at least 8 characters long.', true); - error = true; - } - if ($scope.model.newMasterPassword !== $scope.model.confirmNewMasterPassword) { - validationService.addError(form, 'ConfirmNewMasterPasswordHash', - 'New master password confirmation does not match.', true); - error = true; - } - - if (error) { - return; - } - - var makeResult; - $scope.savePromise = authService.getUserProfile().then(function (profile) { - return cryptoService.makeKeyAndHash(profile.email, model.newMasterPassword); - }).then(function (result) { - makeResult = result; - return cryptoService.hashPassword(model.masterPassword); - }).then(function (hash) { - var encKey = cryptoService.getEncKey(); - var newEncKey = cryptoService.encrypt(encKey.key, makeResult.key, 'raw'); - - var request = { - masterPasswordHash: hash, - newMasterPasswordHash: makeResult.hash, - key: newEncKey - }; - - return apiService.accounts.putPassword(request).$promise; - }).then(function () { - $uibModalInstance.dismiss('cancel'); - authService.logOut(); - $analytics.eventTrack('Changed Password'); - return $state.go('frontend.login.info'); - }).then(function () { - toastr.success('Please log back in.', 'Master Password Changed'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsController.js b/src/app/settings/settingsController.js deleted file mode 100644 index f31cc37d76..0000000000 --- a/src/app/settings/settingsController.js +++ /dev/null @@ -1,143 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsController', function ($scope, $state, $uibModal, apiService, toastr, authService, $localStorage, - $rootScope, cipherService) { - $scope.model = { - profile: {}, - email: null, - disableWebsiteIcons: false - }; - - $scope.$on('$viewContentLoaded', function () { - apiService.accounts.getProfile({}, function (user) { - $scope.model = { - profile: { - name: user.Name, - masterPasswordHint: user.MasterPasswordHint, - culture: user.Culture - }, - email: user.Email, - disableWebsiteIcons: $localStorage.disableWebsiteIcons - }; - - if (user.Organizations) { - var orgs = []; - for (var i = 0; i < user.Organizations.length; i++) { - // Only confirmed - if (user.Organizations[i].Status !== 2) { - continue; - } - - orgs.push({ - id: user.Organizations[i].Id, - name: user.Organizations[i].Name, - status: user.Organizations[i].Status, - type: user.Organizations[i].Type, - enabled: user.Organizations[i].Enabled - }); - } - - $scope.model.organizations = orgs; - } - }); - }); - - $scope.generalSave = function () { - $scope.generalPromise = apiService.accounts.putProfile({}, $scope.model.profile, function (profile) { - authService.setUserProfile(profile).then(function (updatedProfile) { - toastr.success('Account has been updated.', 'Success!'); - }); - }).$promise; - }; - - $scope.passwordHintSave = function () { - $scope.passwordHintPromise = apiService.accounts.putProfile({}, $scope.model.profile, function (profile) { - authService.setUserProfile(profile).then(function (updatedProfile) { - toastr.success('Account has been updated.', 'Success!'); - }); - }).$promise; - }; - - $scope.optionsSave = function () { - $localStorage.disableWebsiteIcons = cipherService.disableWebsiteIcons = $scope.model.disableWebsiteIcons; - $rootScope.vaultCiphers = null; - - toastr.success('Options have been updated.', 'Success!'); - }; - - $scope.changePassword = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsChangePassword.html', - controller: 'settingsChangePasswordController' - }); - }; - - $scope.changeEmail = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsChangeEmail.html', - controller: 'settingsChangeEmailController' - }); - }; - - $scope.viewOrganization = function (org) { - if (org.type === 2) { // 2 = User - scrollToTop(); - toastr.error('You cannot manage this organization.'); - return; - } - - $state.go('backend.org.dashboard', { orgId: org.id }); - }; - - $scope.leaveOrganization = function (org) { - if (!confirm('Are you sure you want to leave this organization (' + org.name + ')?')) { - return; - } - - apiService.organizations.postLeave({ id: org.id }, {}, function (response) { - authService.refreshAccessToken().then(function () { - var index = $scope.model.organizations.indexOf(org); - if (index > -1) { - $scope.model.organizations.splice(index, 1); - } - - toastr.success('You have left the organization.'); - scrollToTop(); - }); - }, function (error) { - toastr.error('Unable to leave this organization.'); - scrollToTop(); - }); - }; - - $scope.sessions = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsSessions.html', - controller: 'settingsSessionsController' - }); - }; - - $scope.delete = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsDelete.html', - controller: 'settingsDeleteController' - }); - }; - - $scope.purge = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsPurge.html', - controller: 'settingsPurgeController' - }); - }; - - function scrollToTop() { - $('html, body').animate({ scrollTop: 0 }, 200); - } - }); diff --git a/src/app/settings/settingsCreateOrganizationController.js b/src/app/settings/settingsCreateOrganizationController.js deleted file mode 100644 index 9f5bbf4a13..0000000000 --- a/src/app/settings/settingsCreateOrganizationController.js +++ /dev/null @@ -1,145 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsCreateOrganizationController', function ($scope, $state, apiService, cryptoService, - toastr, $analytics, authService, constants, appSettings, validationService - // @if !selfHosted - /* jshint ignore:start */ - , stripe - /* jshint ignore:end */ - // @endif - ) { - $scope.plans = constants.plans; - $scope.storageGb = constants.storageGb; - $scope.paymentMethod = 'card'; - $scope.selfHosted = appSettings.selfHosted; - - $scope.model = { - plan: 'free', - additionalSeats: 0, - interval: 'year', - ownedBusiness: false, - additionalStorageGb: null - }; - - $scope.totalPrice = function () { - if ($scope.model.interval === 'month') { - return (($scope.model.additionalSeats || 0) * ($scope.plans[$scope.model.plan].monthlySeatPrice || 0)) + - (($scope.model.additionalStorageGb || 0) * $scope.storageGb.monthlyPrice) + - ($scope.plans[$scope.model.plan].monthlyBasePrice || 0); - } - else { - return (($scope.model.additionalSeats || 0) * ($scope.plans[$scope.model.plan].annualSeatPrice || 0)) + - (($scope.model.additionalStorageGb || 0) * $scope.storageGb.yearlyPrice) + - ($scope.plans[$scope.model.plan].annualBasePrice || 0); - } - }; - - $scope.changePaymentMethod = function (val) { - $scope.paymentMethod = val; - }; - - $scope.changedPlan = function () { - if ($scope.plans[$scope.model.plan].hasOwnProperty('monthPlanType')) { - $scope.model.interval = 'year'; - } - - if ($scope.plans[$scope.model.plan].noAdditionalSeats) { - $scope.model.additionalSeats = 0; - } - else if (!$scope.model.additionalSeats && !$scope.plans[$scope.model.plan].baseSeats && - !$scope.plans[$scope.model.plan].noAdditionalSeats) { - $scope.model.additionalSeats = 1; - } - }; - - $scope.changedBusiness = function () { - if ($scope.model.ownedBusiness) { - $scope.model.plan = 'teams'; - } - }; - - $scope.submit = function (model, form) { - var shareKey = cryptoService.makeShareKey(); - var defaultCollectionCt = cryptoService.encrypt('Default Collection', shareKey.key); - - if ($scope.selfHosted) { - var fileEl = document.getElementById('file'); - var files = fileEl.files; - if (!files || !files.length) { - validationService.addError(form, 'file', 'Select a license file.', true); - return; - } - - var fd = new FormData(); - fd.append('license', files[0]); - fd.append('key', shareKey.ct); - fd.append('collectionName', defaultCollectionCt); - - $scope.submitPromise = apiService.organizations.postLicense(fd).$promise.then(finalizeCreate); - } - else { - if (model.plan === 'free') { - var freeRequest = { - name: model.name, - planType: model.plan, - key: shareKey.ct, - billingEmail: model.billingEmail, - collectionName: defaultCollectionCt - }; - - $scope.submitPromise = apiService.organizations.post(freeRequest).$promise.then(finalizeCreate); - } - else { - var stripeReq = null; - if ($scope.paymentMethod === 'card') { - stripeReq = stripe.card.createToken(model.card); - } - else if ($scope.paymentMethod === 'bank') { - model.bank.currency = 'USD'; - model.bank.country = 'US'; - stripeReq = stripe.bankAccount.createToken(model.bank); - } - else { - return; - } - - $scope.submitPromise = stripeReq.then(function (response) { - var paidRequest = { - name: model.name, - planType: model.interval === 'month' ? $scope.plans[model.plan].monthPlanType : - $scope.plans[model.plan].annualPlanType, - key: shareKey.ct, - paymentToken: response.id, - additionalSeats: model.additionalSeats, - additionalStorageGb: model.additionalStorageGb, - billingEmail: model.billingEmail, - businessName: model.ownedBusiness ? model.businessName : null, - country: $scope.paymentMethod === 'card' ? model.card.address_country : null, - collectionName: defaultCollectionCt - }; - - return apiService.organizations.post(paidRequest).$promise; - }, function (err) { - throw err.message; - }).then(finalizeCreate); - } - } - - function finalizeCreate(result) { - $analytics.eventTrack('Created Organization'); - authService.addProfileOrganizationOwner(result, shareKey.ct); - authService.refreshAccessToken().then(function () { - goToOrg(result.Id); - }, function () { - goToOrg(result.Id); - }); - } - - function goToOrg(id) { - $state.go('backend.org.dashboard', { orgId: id }).then(function () { - toastr.success('Your new organization is ready to go!', 'Organization Created'); - }); - } - }; - }); diff --git a/src/app/settings/settingsDeleteController.js b/src/app/settings/settingsDeleteController.js deleted file mode 100644 index f5d1e303ed..0000000000 --- a/src/app/settings/settingsDeleteController.js +++ /dev/null @@ -1,31 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsDeleteController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics, tokenService) { - $analytics.eventTrack('settingsDeleteController', { category: 'Modal' }); - $scope.submit = function (model) { - var profile; - - $scope.submitPromise = authService.getUserProfile().then(function (theProfile) { - profile = theProfile; - return cryptoService.hashPassword(model.masterPassword); - }).then(function (hash) { - return apiService.accounts.postDelete({ - masterPasswordHash: hash - }).$promise; - }).then(function () { - $uibModalInstance.dismiss('cancel'); - authService.logOut(); - tokenService.clearTwoFactorToken(profile.email); - $analytics.eventTrack('Deleted Account'); - return $state.go('frontend.login.info'); - }).then(function () { - toastr.success('Your account has been closed and all associated data has been deleted.', 'Account Deleted'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsDomainsController.js b/src/app/settings/settingsDomainsController.js deleted file mode 100644 index cd193b4012..0000000000 --- a/src/app/settings/settingsDomainsController.js +++ /dev/null @@ -1,103 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsDomainsController', function ($scope, $state, apiService, toastr, $analytics, $uibModal) { - $scope.globalEquivalentDomains = []; - $scope.equivalentDomains = []; - - apiService.settings.getDomains({}, function (response) { - var i; - if (response.EquivalentDomains) { - for (i = 0; i < response.EquivalentDomains.length; i++) { - $scope.equivalentDomains.push(response.EquivalentDomains[i].join(', ')); - } - } - - if (response.GlobalEquivalentDomains) { - for (i = 0; i < response.GlobalEquivalentDomains.length; i++) { - $scope.globalEquivalentDomains.push({ - domains: response.GlobalEquivalentDomains[i].Domains.join(', '), - excluded: response.GlobalEquivalentDomains[i].Excluded, - key: response.GlobalEquivalentDomains[i].Type - }); - } - } - }); - - $scope.toggleExclude = function (globalDomain) { - globalDomain.excluded = !globalDomain.excluded; - }; - - $scope.customize = function (globalDomain) { - globalDomain.excluded = true; - $scope.equivalentDomains.push(globalDomain.domains); - }; - - $scope.delete = function (i) { - $scope.equivalentDomains.splice(i, 1); - $scope.$emit('removeAppendedDropdownMenu'); - }; - - $scope.addEdit = function (i) { - var addEditModal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsAddEditEquivalentDomain.html', - controller: 'settingsAddEditEquivalentDomainController', - resolve: { - domainIndex: function () { return i; }, - domains: function () { return i !== null ? $scope.equivalentDomains[i] : null; } - } - }); - - addEditModal.result.then(function (returnObj) { - if (returnObj.domains) { - returnObj.domains = returnObj.domains.split(' ').join('').split(',').join(', '); - } - - if (returnObj.index !== null) { - $scope.equivalentDomains[returnObj.index] = returnObj.domains; - } - else { - $scope.equivalentDomains.push(returnObj.domains); - } - }); - }; - - $scope.saveGlobal = function () { - $scope.globalPromise = save(); - }; - - $scope.saveCustom = function () { - $scope.customPromise = save(); - }; - - var save = function () { - var request = { - ExcludedGlobalEquivalentDomains: [], - EquivalentDomains: [] - }; - - for (var i = 0; i < $scope.globalEquivalentDomains.length; i++) { - if ($scope.globalEquivalentDomains[i].excluded) { - request.ExcludedGlobalEquivalentDomains.push($scope.globalEquivalentDomains[i].key); - } - } - - for (i = 0; i < $scope.equivalentDomains.length; i++) { - request.EquivalentDomains.push($scope.equivalentDomains[i].split(' ').join('').split(',')); - } - - if (!request.EquivalentDomains.length) { - request.EquivalentDomains = null; - } - - if (!request.ExcludedGlobalEquivalentDomains.length) { - request.ExcludedGlobalEquivalentDomains = null; - } - - return apiService.settings.putDomains(request, function (domains) { - $analytics.eventTrack('Saved Equivalent Domains'); - toastr.success('Domains have been updated.', 'Success!'); - }).$promise; - }; - }); diff --git a/src/app/settings/settingsModule.js b/src/app/settings/settingsModule.js deleted file mode 100644 index 4c5aa7f7c2..0000000000 --- a/src/app/settings/settingsModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.settings', ['ui.bootstrap', 'toastr']); diff --git a/src/app/settings/settingsPremiumController.js b/src/app/settings/settingsPremiumController.js deleted file mode 100644 index ca9cd7f326..0000000000 --- a/src/app/settings/settingsPremiumController.js +++ /dev/null @@ -1,136 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsPremiumController', function ($scope, $state, apiService, toastr, $analytics, authService, - constants, $timeout, appSettings, validationService - // @if !selfHosted - /* jshint ignore:start */ - , stripe - /* jshint ignore:end */ - // @endif - ) { - var profile = null; - - authService.getUserProfile().then(function (theProfile) { - profile = theProfile; - if (profile && profile.premium) { - return $state.go('backend.user.settingsBilling'); - } - }); - - $scope.selfHosted = appSettings.selfHosted; - - var btInstance = null; - $scope.storageGbPrice = constants.storageGb.yearlyPrice; - $scope.premiumPrice = constants.premium.price; - $scope.paymentMethod = 'card'; - $scope.dropinLoaded = false; - - $scope.model = { - additionalStorageGb: null - }; - - $scope.changePaymentMethod = function (val) { - $scope.paymentMethod = val; - if ($scope.paymentMethod !== 'paypal') { - return; - } - - braintree.dropin.create({ - authorization: appSettings.braintreeKey, - container: '#bt-dropin-container', - paymentOptionPriority: ['paypal'], - paypal: { - flow: 'vault', - buttonStyle: { - label: 'pay', - size: 'medium', - shape: 'pill', - color: 'blue' - } - } - }, function (createErr, instance) { - if (createErr) { - console.error(createErr); - return; - } - - btInstance = instance; - $timeout(function () { - $scope.dropinLoaded = true; - }); - }); - }; - - $scope.totalPrice = function () { - return $scope.premiumPrice + (($scope.model.additionalStorageGb || 0) * $scope.storageGbPrice); - }; - - $scope.submit = function (model, form) { - if ($scope.selfHosted) { - if (profile && !profile.emailVerified) { - validationService.addError(form, null, 'Your account\'s email address first must be verified.', true); - return; - } - - var fileEl = document.getElementById('file'); - var files = fileEl.files; - if (!files || !files.length) { - validationService.addError(form, 'file', 'Select a license file.', true); - return; - } - - var fd = new FormData(); - fd.append('license', files[0]); - - $scope.submitPromise = apiService.accounts.postPremium(fd).$promise.then(function (result) { - return finalizePremium(); - }); - } - else { - $scope.submitPromise = getPaymentToken(model).then(function (token) { - if (!token) { - throw 'No payment token.'; - } - - var fd = new FormData(); - fd.append('paymentToken', token); - fd.append('additionalStorageGb', model.additionalStorageGb || 0); - - return apiService.accounts.postPremium(fd).$promise; - }, function (err) { - throw err; - }).then(function (result) { - return finalizePremium(); - }); - } - }; - - function finalizePremium() { - return authService.updateProfilePremium(true).then(function () { - $analytics.eventTrack('Signed Up Premium'); - return authService.refreshAccessToken(); - }).then(function () { - return $state.go('backend.user.settingsBilling'); - }).then(function () { - toastr.success('Premium upgrade complete.', 'Success'); - }); - } - - function getPaymentToken(model) { - if ($scope.paymentMethod === 'paypal') { - return btInstance.requestPaymentMethod().then(function (payload) { - return payload.nonce; - }).catch(function (err) { - throw err.message; - }); - } - else { - return stripe.card.createToken(model.card).then(function (response) { - return response.id; - }).catch(function (err) { - throw err.message; - }); - } - } - }); diff --git a/src/app/settings/settingsPurgeController.js b/src/app/settings/settingsPurgeController.js deleted file mode 100644 index 74859d784e..0000000000 --- a/src/app/settings/settingsPurgeController.js +++ /dev/null @@ -1,24 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsPurgeController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics, tokenService) { - $analytics.eventTrack('settingsPurgeController', { category: 'Modal' }); - $scope.submit = function (model) { - $scope.submitPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - return apiService.ciphers.purge({ - masterPasswordHash: hash - }).$promise; - }).then(function () { - $uibModalInstance.dismiss('cancel'); - $analytics.eventTrack('Purged Vault'); - return $state.go('backend.user.vault', { refreshFromServer: true }); - }).then(function () { - toastr.success('All items in your vault have been deleted.', 'Vault Purged'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsSessionsController.js b/src/app/settings/settingsSessionsController.js deleted file mode 100644 index 9f726a505b..0000000000 --- a/src/app/settings/settingsSessionsController.js +++ /dev/null @@ -1,32 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsSessionsController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, - authService, tokenService, toastr, $analytics) { - $analytics.eventTrack('settingsSessionsController', { category: 'Modal' }); - $scope.submit = function (model) { - var hash, profile; - - $scope.submitPromise = cryptoService.hashPassword(model.masterPassword).then(function (theHash) { - hash = theHash; - return authService.getUserProfile(); - }).then(function (theProfile) { - profile = theProfile; - return apiService.accounts.putSecurityStamp({ - masterPasswordHash: hash - }).$promise; - }).then(function () { - $uibModalInstance.dismiss('cancel'); - authService.logOut(); - tokenService.clearTwoFactorToken(profile.email); - $analytics.eventTrack('Deauthorized Sessions'); - return $state.go('frontend.login.info'); - }).then(function () { - toastr.success('Please log back in.', 'All Sessions Deauthorized'); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/settingsTwoStepAuthenticatorController.js b/src/app/settings/settingsTwoStepAuthenticatorController.js deleted file mode 100644 index 18fcdf04e6..0000000000 --- a/src/app/settings/settingsTwoStepAuthenticatorController.js +++ /dev/null @@ -1,108 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepAuthenticatorController', function ($scope, apiService, $uibModalInstance, cryptoService, - authService, $q, toastr, $analytics, constants, $timeout) { - $analytics.eventTrack('settingsTwoStepAuthenticatorController', { category: 'Modal' }); - var _issuer = 'Bitwarden', - _profile = null, - _masterPasswordHash, - _key = null; - - $timeout(function () { - $("#masterPassword").focus(); - }); - - $scope.auth = function (model) { - var response = null; - $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - _masterPasswordHash = hash; - return apiService.twoFactor.getAuthenticator({}, { - masterPasswordHash: _masterPasswordHash - }).$promise; - }).then(function (apiResponse) { - response = apiResponse; - return authService.getUserProfile(); - }).then(function (profile) { - _profile = profile; - $scope.account = _profile.email; - processResponse(response); - }); - }; - - function formatString(s) { - if (!s) { - return null; - } - - return s.replace(/(.{4})/g, '$1 ').trim().toUpperCase(); - } - - function processResponse(response) { - $scope.enabled = response.Enabled; - _key = response.Key; - - $scope.model = { - key: formatString(_key), - qr: 'https://chart.googleapis.com/chart?chs=160x160&chld=L|0&cht=qr&chl=otpauth://totp/' + - _issuer + ':' + encodeURIComponent(_profile.email) + - '%3Fsecret=' + encodeURIComponent(_key) + - '%26issuer=' + _issuer - }; - $scope.updateModel = { - token: null - }; - } - - $scope.submit = function (model) { - if (!model || !model.token) { - disable(); - return; - } - - update(model); - }; - - function disable() { - if (!confirm('Are you sure you want to disable the authenticator app provider?')) { - return; - } - - $scope.submitPromise = apiService.twoFactor.disable({}, { - masterPasswordHash: _masterPasswordHash, - type: constants.twoFactorProvider.authenticator - }, function (response) { - $analytics.eventTrack('Disabled Two-step Authenticator'); - toastr.success('Authenticator app has been disabled.'); - $scope.enabled = response.Enabled; - $scope.close(); - }).$promise; - } - - function update(model) { - $scope.submitPromise = apiService.twoFactor.putAuthenticator({}, { - token: model.token.replace(' ', ''), - key: _key, - masterPasswordHash: _masterPasswordHash - }, function (response) { - $analytics.eventTrack('Enabled Two-step Authenticator'); - processResponse(response); - model.token = null; - }).$promise; - } - - var closing = false; - $scope.close = function () { - closing = true; - $uibModalInstance.close($scope.enabled); - }; - - $scope.$on('modal.closing', function (e, reason, closed) { - if (closing) { - return; - } - - e.preventDefault(); - $scope.close(); - }); - }); diff --git a/src/app/settings/settingsTwoStepController.js b/src/app/settings/settingsTwoStepController.js deleted file mode 100644 index 58cd2efcc9..0000000000 --- a/src/app/settings/settingsTwoStepController.js +++ /dev/null @@ -1,83 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepController', function ($scope, apiService, toastr, $analytics, constants, - $filter, $uibModal, authService) { - $scope.providers = $filter('filter')(constants.twoFactorProviderInfo, { organization: false }); - $scope.premium = true; - - authService.getUserProfile().then(function (profile) { - $scope.premium = profile.premium; - return apiService.twoFactor.list({}).$promise; - }).then(function (response) { - if (response.Data) { - for (var i = 0; i < response.Data.length; i++) { - if (!response.Data[i].Enabled) { - continue; - } - - var provider = $filter('filter')($scope.providers, { type: response.Data[i].Type }); - if (provider.length) { - provider[0].enabled = true; - } - } - } - - return; - }); - - $scope.edit = function (provider) { - if (!$scope.premium && !provider.free) { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/premiumRequired.html', - controller: 'premiumRequiredController' - }); - return; - } - - if (provider.type === constants.twoFactorProvider.authenticator) { - typeName = 'Authenticator'; - } - else if (provider.type === constants.twoFactorProvider.email) { - typeName = 'Email'; - } - else if (provider.type === constants.twoFactorProvider.yubikey) { - typeName = 'Yubi'; - } - else if (provider.type === constants.twoFactorProvider.duo) { - typeName = 'Duo'; - } - else if (provider.type === constants.twoFactorProvider.u2f) { - typeName = 'U2f'; - } - else { - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsTwoStep' + typeName + '.html', - controller: 'settingsTwoStep' + typeName + 'Controller', - resolve: { - enabled: function () { return provider.enabled; }, - orgId: function () { return null; } - } - }); - - modal.result.then(function (enabled) { - if (enabled || enabled === false) { - // do not adjust when undefined or null - provider.enabled = enabled; - } - }); - }; - - $scope.viewRecover = function () { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsTwoStepRecover.html', - controller: 'settingsTwoStepRecoverController' - }); - }; - }); diff --git a/src/app/settings/settingsTwoStepDuoController.js b/src/app/settings/settingsTwoStepDuoController.js deleted file mode 100644 index ad1b14fd07..0000000000 --- a/src/app/settings/settingsTwoStepDuoController.js +++ /dev/null @@ -1,124 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepDuoController', function ($scope, apiService, $uibModalInstance, cryptoService, - toastr, $analytics, constants, $timeout, orgId) { - $analytics.eventTrack('settingsTwoStepDuoController', { category: 'Modal' }); - var _masterPasswordHash; - - $scope.updateModel = { - token: null, - host: null, - ikey: null, - skey: null - }; - - $timeout(function () { - $("#masterPassword").focus(); - }); - - $scope.auth = function (model) { - $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - _masterPasswordHash = hash; - var requestModel = { - masterPasswordHash: _masterPasswordHash - }; - - if (orgId) { - return apiService.twoFactor.getOrganizationDuo({ orgId: orgId }, requestModel).$promise; - } - else { - return apiService.twoFactor.getDuo({}, requestModel).$promise; - } - }).then(function (apiResponse) { - processResult(apiResponse); - $scope.authed = true; - }); - }; - - $scope.submit = function (model) { - if ($scope.enabled) { - disable(); - return; - } - - update(model); - }; - - function disable() { - if (!confirm('Are you sure you want to disable the Duo provider?')) { - return; - } - - if (orgId) { - $scope.submitPromise = apiService.twoFactor.disableOrganization({ orgId: orgId }, { - masterPasswordHash: _masterPasswordHash, - type: constants.twoFactorProvider.organizationDuo - }, function (response) { - $analytics.eventTrack('Disabled Two-step Organization Duo'); - toastr.success('Duo has been disabled.'); - $scope.enabled = response.Enabled; - $scope.close(); - }).$promise; - } - else { - $scope.submitPromise = apiService.twoFactor.disable({}, { - masterPasswordHash: _masterPasswordHash, - type: constants.twoFactorProvider.duo - }, function (response) { - $analytics.eventTrack('Disabled Two-step Duo'); - toastr.success('Duo has been disabled.'); - $scope.enabled = response.Enabled; - $scope.close(); - }).$promise; - } - } - - function update(model) { - var requestModel = { - integrationKey: model.ikey, - secretKey: model.skey, - host: model.host, - masterPasswordHash: _masterPasswordHash - }; - - if (orgId) { - $scope.submitPromise = apiService.twoFactor.putOrganizationDuo({ orgId: orgId }, requestModel, - function (response) { - $analytics.eventTrack('Enabled Two-step Organization Duo'); - processResult(response); - }).$promise; - } - else { - $scope.submitPromise = apiService.twoFactor.putDuo({}, requestModel, - function (response) { - $analytics.eventTrack('Enabled Two-step Duo'); - processResult(response); - }).$promise; - } - } - - function processResult(response) { - $scope.enabled = response.Enabled; - $scope.updateModel = { - ikey: response.IntegrationKey, - skey: response.SecretKey, - host: response.Host - }; - } - - var closing = false; - $scope.close = function () { - closing = true; - $uibModalInstance.close($scope.enabled); - }; - - $scope.$on('modal.closing', function (e, reason, closed) { - if (closing) { - return; - } - - e.preventDefault(); - $scope.close(); - }); - }); diff --git a/src/app/settings/settingsTwoStepEmailController.js b/src/app/settings/settingsTwoStepEmailController.js deleted file mode 100644 index 42133f7a1f..0000000000 --- a/src/app/settings/settingsTwoStepEmailController.js +++ /dev/null @@ -1,114 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepEmailController', function ($scope, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics, constants, $timeout) { - $analytics.eventTrack('settingsTwoStepEmailController', { category: 'Modal' }); - var _profile = null, - _masterPasswordHash; - - $scope.updateModel = { - token: null, - email: null - }; - - $timeout(function () { - $("#masterPassword").focus(); - }); - - $scope.auth = function (model) { - var response = null; - $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - _masterPasswordHash = hash; - return apiService.twoFactor.getEmail({}, { - masterPasswordHash: _masterPasswordHash - }).$promise; - }).then(function (apiResponse) { - response = apiResponse; - return authService.getUserProfile(); - }).then(function (profile) { - _profile = profile; - $scope.enabled = response.Enabled; - $scope.updateModel.email = $scope.enabled ? response.Email : _profile.email; - $scope.authed = true; - }); - }; - - $scope.sendEmail = function (model) { - $scope.emailError = false; - $scope.emailSuccess = false; - - if (!model || !model.email || model.email.indexOf('@') < 0) { - $scope.emailError = true; - $scope.emailSuccess = false; - return; - } - - $scope.emailLoading = true; - apiService.twoFactor.sendEmail({}, { - masterPasswordHash: _masterPasswordHash, - email: model.email - }, function (response) { - $scope.emailError = false; - $scope.emailSuccess = true; - $scope.emailLoading = false; - }, function (response) { - $scope.emailError = true; - $scope.emailSuccess = false; - $scope.emailLoading = false; - }); - }; - - $scope.submit = function (model) { - if (!model || !model.token) { - disable(); - return; - } - - update(model); - }; - - function disable() { - if (!confirm('Are you sure you want to disable the email provider?')) { - return; - } - - $scope.submitPromise = apiService.twoFactor.disable({}, { - masterPasswordHash: _masterPasswordHash, - type: constants.twoFactorProvider.email - }, function (response) { - $analytics.eventTrack('Disabled Two-step Email'); - toastr.success('Email has been disabled.'); - $scope.enabled = response.Enabled; - $scope.close(); - }).$promise; - } - - function update(model) { - $scope.submitPromise = apiService.twoFactor.putEmail({}, { - email: model.email.toLowerCase().trim(), - token: model.token.replace(' ', ''), - masterPasswordHash: _masterPasswordHash - }, function (response) { - $analytics.eventTrack('Enabled Two-step Email'); - $scope.enabled = response.Enabled; - model.email = response.Email; - model.token = null; - }).$promise; - } - - var closing = false; - $scope.close = function () { - closing = true; - $uibModalInstance.close($scope.enabled); - }; - - $scope.$on('modal.closing', function (e, reason, closed) { - if (closing) { - return; - } - - e.preventDefault(); - $scope.close(); - }); - }); diff --git a/src/app/settings/settingsTwoStepRecoverController.js b/src/app/settings/settingsTwoStepRecoverController.js deleted file mode 100644 index 4c2b4dd83f..0000000000 --- a/src/app/settings/settingsTwoStepRecoverController.js +++ /dev/null @@ -1,49 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepRecoverController', function ($scope, apiService, $uibModalInstance, cryptoService, - $analytics, $timeout) { - $analytics.eventTrack('settingsTwoStepRecoverController', { category: 'Modal' }); - $scope.code = null; - - $scope.auth = function (model) { - $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - return apiService.twoFactor.getRecover({}, { - masterPasswordHash: hash - }).$promise; - }).then(function (apiResponse) { - $scope.code = formatString(apiResponse.Code); - $scope.authed = true; - }); - }; - - $timeout(function () { - $("#masterPassword").focus(); - }); - - $scope.print = function () { - if (!$scope.code) { - return; - } - - $analytics.eventTrack('Print Recovery Code'); - var w = window.open(); - w.document.write('

Bitwarden two-step login recovery code:

' + - '' + $scope.code + '' + - '

' + new Date() + '

'); - w.print(); - w.close(); - }; - - function formatString(s) { - if (!s) { - return null; - } - - return s.replace(/(.{4})/g, '$1 ').trim().toUpperCase(); - } - - $scope.close = function () { - $uibModalInstance.close(); - }; - }); diff --git a/src/app/settings/settingsTwoStepU2fController.js b/src/app/settings/settingsTwoStepU2fController.js deleted file mode 100644 index c92cf2842d..0000000000 --- a/src/app/settings/settingsTwoStepU2fController.js +++ /dev/null @@ -1,117 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepU2fController', function ($scope, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics, constants, $timeout, $window) { - $analytics.eventTrack('settingsTwoStepU2fController', { category: 'Modal' }); - var _masterPasswordHash; - var closed = false; - - $scope.deviceResponse = null; - $scope.deviceListening = false; - $scope.deviceError = false; - - $timeout(function () { - $("#masterPassword").focus(); - }); - - $scope.auth = function (model) { - $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - _masterPasswordHash = hash; - return apiService.twoFactor.getU2f({}, { - masterPasswordHash: _masterPasswordHash - }).$promise; - }).then(function (response) { - $scope.enabled = response.Enabled; - $scope.challenge = response.Challenge; - $scope.authed = true; - return $scope.readDevice(); - }); - }; - - $scope.readDevice = function () { - if (closed || $scope.enabled) { - return; - } - - console.log('listening for key...'); - - $scope.deviceResponse = null; - $scope.deviceError = false; - $scope.deviceListening = true; - - $window.u2f.register($scope.challenge.AppId, [{ - version: $scope.challenge.Version, - challenge: $scope.challenge.Challenge - }], [], function (data) { - $scope.deviceListening = false; - if (data.errorCode === 5) { - $scope.readDevice(); - return; - } - else if (data.errorCode) { - $timeout(function () { - $scope.deviceError = true; - }); - console.log('error: ' + data.errorCode); - return; - } - - $timeout(function () { - $scope.deviceResponse = JSON.stringify(data); - }); - }, 10); - }; - - $scope.submit = function () { - if ($scope.enabled) { - disable(); - return; - } - - update(); - }; - - function disable() { - if (!confirm('Are you sure you want to disable the U2F provider?')) { - return; - } - - $scope.submitPromise = apiService.twoFactor.disable({}, { - masterPasswordHash: _masterPasswordHash, - type: constants.twoFactorProvider.u2f - }, function (response) { - $analytics.eventTrack('Disabled Two-step U2F'); - toastr.success('U2F has been disabled.'); - $scope.enabled = response.Enabled; - $scope.close(); - }).$promise; - } - - function update() { - $scope.submitPromise = apiService.twoFactor.putU2f({}, { - deviceResponse: $scope.deviceResponse, - masterPasswordHash: _masterPasswordHash - }, function (response) { - $analytics.eventTrack('Enabled Two-step U2F'); - $scope.enabled = response.Enabled; - $scope.challenge = null; - $scope.deviceResponse = null; - $scope.deviceError = false; - }).$promise; - } - - $scope.close = function () { - closed = true; - $uibModalInstance.close($scope.enabled); - }; - - $scope.$on('modal.closing', function (e, reason, isClosed) { - if (closed) { - return; - } - - e.preventDefault(); - $scope.close(); - }); - }); diff --git a/src/app/settings/settingsTwoStepYubiController.js b/src/app/settings/settingsTwoStepYubiController.js deleted file mode 100644 index 7adfe28256..0000000000 --- a/src/app/settings/settingsTwoStepYubiController.js +++ /dev/null @@ -1,116 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoStepYubiController', function ($scope, apiService, $uibModalInstance, cryptoService, - authService, toastr, $analytics, constants, $timeout) { - $analytics.eventTrack('settingsTwoStepYubiController', { category: 'Modal' }); - var _profile = null, - _masterPasswordHash; - - $timeout(function () { - $("#masterPassword").focus(); - }); - - $scope.auth = function (model) { - var response = null; - $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { - _masterPasswordHash = hash; - return apiService.twoFactor.getYubi({}, { - masterPasswordHash: _masterPasswordHash - }).$promise; - }).then(function (apiResponse) { - response = apiResponse; - return authService.getUserProfile(); - }).then(function (profile) { - _profile = profile; - processResult(response); - $scope.authed = true; - }); - }; - - $scope.remove = function (model) { - model.key = null; - model.existingKey = null; - }; - - $scope.submit = function (model) { - $scope.submitPromise = apiService.twoFactor.putYubi({}, { - key1: model.key1.key, - key2: model.key2.key, - key3: model.key3.key, - nfc: model.nfc, - masterPasswordHash: _masterPasswordHash - }, function (response) { - $analytics.eventTrack('Saved Two-step YubiKey'); - toastr.success('YubiKey saved.'); - processResult(response); - }).$promise; - }; - - $scope.disable = function () { - if (!confirm('Are you sure you want to disable the YubiKey provider?')) { - return; - } - - $scope.disableLoading = true; - $scope.submitPromise = apiService.twoFactor.disable({}, { - masterPasswordHash: _masterPasswordHash, - type: constants.twoFactorProvider.yubikey - }, function (response) { - $scope.disableLoading = false; - $analytics.eventTrack('Disabled Two-step YubiKey'); - toastr.success('YubiKey has been disabled.'); - $scope.enabled = response.Enabled; - $scope.close(); - }, function (response) { - toastr.error('Failed to disable.'); - $scope.disableLoading = false; - }).$promise; - }; - - function processResult(response) { - $scope.enabled = response.Enabled; - $scope.updateModel = { - key1: { - key: response.Key1, - existingKey: padRight(response.Key1, '*', 44) - }, - key2: { - key: response.Key2, - existingKey: padRight(response.Key2, '*', 44) - }, - key3: { - key: response.Key3, - existingKey: padRight(response.Key3, '*', 44) - }, - nfc: response.Nfc === true || !response.Enabled - }; - } - - function padRight(str, character, size) { - if (!str || !character || str.length >= size) { - return str; - } - - var max = (size - str.length) / character.length; - for (var i = 0; i < max; i++) { - str += character; - } - return str; - } - - var closing = false; - $scope.close = function () { - closing = true; - $uibModalInstance.close($scope.enabled); - }; - - $scope.$on('modal.closing', function (e, reason, closed) { - if (closing) { - return; - } - - e.preventDefault(); - $scope.close(); - }); - }); diff --git a/src/app/settings/settingsUpdateKeyController.js b/src/app/settings/settingsUpdateKeyController.js deleted file mode 100644 index 5111460449..0000000000 --- a/src/app/settings/settingsUpdateKeyController.js +++ /dev/null @@ -1,81 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsUpdateKeyController', function ($scope, $state, apiService, $uibModalInstance, cipherService, - cryptoService, authService, validationService, toastr, $analytics, $q) { - $analytics.eventTrack('settingsUpdateKeyController', { category: 'Modal' }); - - $scope.save = function (form) { - var encKey = cryptoService.getEncKey(); - if (encKey) { - validationService.addError(form, 'MasterPasswordHash', - 'You do not need to update. You are already using the new encryption key.', true); - return; - } - - $scope.savePromise = cryptoService.hashPassword($scope.masterPassword).then(function (hash) { - return updateKey(hash); - }).then(function () { - $uibModalInstance.dismiss('cancel'); - authService.logOut(); - $analytics.eventTrack('Key Updated'); - return $state.go('frontend.login.info'); - }, function (e) { - throw e ? e : 'Error occurred.'; - }).then(function () { - toastr.success('Please log back in. If you are using other Bitwarden applications, ' + - 'log out and back in to those as well.', 'Key Updated', { timeOut: 10000 }); - }); - }; - - function updateKey(masterPasswordHash) { - var madeEncKey = cryptoService.makeEncKey(null); - - var reencryptedCiphers = []; - var ciphersPromise = apiService.ciphers.list({}, function (encryptedCiphers) { - var filteredEncryptedCiphers = []; - for (var i = 0; i < encryptedCiphers.Data.length; i++) { - if (encryptedCiphers.Data[i].OrganizationId) { - continue; - } - - filteredEncryptedCiphers.push(encryptedCiphers.Data[i]); - } - - var unencryptedCiphers = cipherService.decryptCiphers(filteredEncryptedCiphers); - reencryptedCiphers = cipherService.encryptCiphers(unencryptedCiphers, madeEncKey.encKey); - }).$promise; - - var reencryptedFolders = []; - var foldersPromise = apiService.folders.list({}, function (encryptedFolders) { - var unencryptedFolders = cipherService.decryptFolders(encryptedFolders.Data); - reencryptedFolders = cipherService.encryptFolders(unencryptedFolders, madeEncKey.encKey); - }).$promise; - - var privateKey = cryptoService.getPrivateKey('raw'), - reencryptedPrivateKey = null; - if (privateKey) { - reencryptedPrivateKey = cryptoService.encrypt(privateKey, madeEncKey.encKey, 'raw'); - } - - return $q.all([ciphersPromise, foldersPromise]).then(function () { - var request = { - masterPasswordHash: masterPasswordHash, - ciphers: reencryptedCiphers, - folders: reencryptedFolders, - privateKey: reencryptedPrivateKey, - key: madeEncKey.encKeyEnc - }; - - return apiService.accounts.putKey(request).$promise; - }, function () { - throw 'Error while encrypting data.'; - }).then(function () { - cryptoService.setEncKey(madeEncKey.encKey, null, true); - }); - } - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/settings/two-factor-authenticator.component.html b/src/app/settings/two-factor-authenticator.component.html new file mode 100644 index 0000000000..1eaa9b986a --- /dev/null +++ b/src/app/settings/two-factor-authenticator.component.html @@ -0,0 +1,72 @@ + diff --git a/src/app/settings/two-factor-authenticator.component.ts b/src/app/settings/two-factor-authenticator.component.ts new file mode 100644 index 0000000000..ab52326733 --- /dev/null +++ b/src/app/settings/two-factor-authenticator.component.ts @@ -0,0 +1,70 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { UpdateTwoFactorAuthenticatorRequest } from 'jslib/models/request/updateTwoFactorAuthenticatorRequest'; +import { TwoFactorAuthenticatorResponse } from 'jslib/models/response/twoFactorAuthenticatorResponse'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; + +import { TwoFactorBaseComponent } from './two-factor-base.component'; + +@Component({ + selector: 'app-two-factor-authenticator', + templateUrl: 'two-factor-authenticator.component.html', +}) +export class TwoFactorAuthenticatorComponent extends TwoFactorBaseComponent { + key: string; + qr: string; + token: string; + formPromise: Promise; + + constructor(apiService: ApiService, i18nService: I18nService, + analytics: Angulartics2, toasterService: ToasterService, + private userService: UserService, platformUtilsService: PlatformUtilsService) { + super(apiService, i18nService, analytics, toasterService, platformUtilsService, + TwoFactorProviderType.Authenticator); + } + + auth(authResponse: any) { + super.auth(authResponse); + return this.processResponse(authResponse.response); + } + + submit() { + if (this.enabled) { + return super.disable(this.formPromise); + } else { + return this.enable(); + } + } + + protected enable() { + const request = new UpdateTwoFactorAuthenticatorRequest(); + request.masterPasswordHash = this.masterPasswordHash; + request.token = this.token; + request.key = this.key; + + return super.enable(async () => { + this.formPromise = this.apiService.putTwoFactorAuthenticator(request); + const response = await this.formPromise; + await this.processResponse(response); + }); + } + + private async processResponse(response: TwoFactorAuthenticatorResponse) { + this.token = null; + this.enabled = response.enabled; + this.key = response.key; + this.qr = 'https://chart.googleapis.com/chart?chs=160x160&chld=L|0&cht=qr&chl=otpauth://totp/' + + 'Bitwarden:' + encodeURIComponent(await this.userService.getEmail()) + + '%3Fsecret=' + encodeURIComponent(this.key) + + '%26issuer=Bitwarden'; + } +} diff --git a/src/app/settings/two-factor-base.component.ts b/src/app/settings/two-factor-base.component.ts new file mode 100644 index 0000000000..be4c785da9 --- /dev/null +++ b/src/app/settings/two-factor-base.component.ts @@ -0,0 +1,65 @@ +import { + EventEmitter, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; +import { TwoFactorProviderRequest } from 'jslib/models/request/twoFactorProviderRequest'; + +export abstract class TwoFactorBaseComponent { + @Output() onUpdated = new EventEmitter(); + + twoFactorProviderType = TwoFactorProviderType; + enabled = false; + authed = false; + + protected masterPasswordHash: string; + + constructor(protected apiService: ApiService, protected i18nService: I18nService, + protected analytics: Angulartics2, protected toasterService: ToasterService, + protected platformUtilsService: PlatformUtilsService, private type: TwoFactorProviderType) { } + + protected auth(authResponse: any) { + this.masterPasswordHash = authResponse.masterPasswordHash; + this.authed = true; + } + + protected async enable(enableFunction: () => Promise) { + try { + await enableFunction(); + this.analytics.eventTrack.next({ + action: 'Enabled Two-step ' + TwoFactorProviderType[this.type].toString(), + }); + this.onUpdated.emit(true); + } catch { } + } + + protected async disable(promise: Promise) { + const confirmed = await this.platformUtilsService.showDialog(this.i18nService.t('twoStepDisableDesc'), + this.i18nService.t('disable'), this.i18nService.t('yes'), this.i18nService.t('no'), 'warning'); + if (!confirmed) { + return; + } + + try { + const request = new TwoFactorProviderRequest(); + request.masterPasswordHash = this.masterPasswordHash; + request.type = this.type; + promise = this.apiService.putTwoFactorDisable(request); + await promise; + this.enabled = false; + this.analytics.eventTrack.next({ + action: 'Disabled Two-step ' + TwoFactorProviderType[this.type].toString(), + }); + this.toasterService.popAsync('success', null, this.i18nService.t('twoStepDisabled')); + this.onUpdated.emit(false); + } catch { } + } +} diff --git a/src/app/settings/two-factor-duo.component.html b/src/app/settings/two-factor-duo.component.html new file mode 100644 index 0000000000..9338ded425 --- /dev/null +++ b/src/app/settings/two-factor-duo.component.html @@ -0,0 +1,57 @@ + diff --git a/src/app/settings/two-factor-duo.component.ts b/src/app/settings/two-factor-duo.component.ts new file mode 100644 index 0000000000..5f5c3af3f2 --- /dev/null +++ b/src/app/settings/two-factor-duo.component.ts @@ -0,0 +1,66 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; +import { UpdateTwoFactorDuoRequest } from 'jslib/models/request/updateTwoFactorDuoRequest'; +import { TwoFactorDuoResponse } from 'jslib/models/response/twoFactorDuoResponse'; + +import { TwoFactorBaseComponent } from './two-factor-base.component'; + +@Component({ + selector: 'app-two-factor-duo', + templateUrl: 'two-factor-duo.component.html', +}) +export class TwoFactorDuoComponent extends TwoFactorBaseComponent { + ikey: string; + skey: string; + host: string; + formPromise: Promise; + + constructor(apiService: ApiService, i18nService: I18nService, + analytics: Angulartics2, toasterService: ToasterService, + platformUtilsService: PlatformUtilsService) { + super(apiService, i18nService, analytics, toasterService, platformUtilsService, + TwoFactorProviderType.Duo); + } + + auth(authResponse: any) { + super.auth(authResponse); + this.processResponse(authResponse.response); + } + + submit() { + if (this.enabled) { + return super.disable(this.formPromise); + } else { + return this.enable(); + } + } + + protected enable() { + const request = new UpdateTwoFactorDuoRequest(); + request.masterPasswordHash = this.masterPasswordHash; + request.integrationKey = this.ikey; + request.secretKey = this.skey; + request.host = this.host; + + return super.enable(async () => { + this.formPromise = this.apiService.putTwoFactorDuo(request); + const response = await this.formPromise; + await this.processResponse(response); + }); + } + + private processResponse(response: TwoFactorDuoResponse) { + this.ikey = response.integrationKey; + this.skey = response.secretKey; + this.host = response.host; + this.enabled = response.enabled; + } +} diff --git a/src/app/settings/two-factor-email.component.html b/src/app/settings/two-factor-email.component.html new file mode 100644 index 0000000000..c202d57678 --- /dev/null +++ b/src/app/settings/two-factor-email.component.html @@ -0,0 +1,59 @@ + diff --git a/src/app/settings/two-factor-email.component.ts b/src/app/settings/two-factor-email.component.ts new file mode 100644 index 0000000000..f72422a968 --- /dev/null +++ b/src/app/settings/two-factor-email.component.ts @@ -0,0 +1,80 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { TwoFactorEmailRequest } from 'jslib/models/request/twoFactorEmailRequest'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; +import { UpdateTwoFactorEmailRequest } from 'jslib/models/request/updateTwoFactorEmailRequest'; +import { TwoFactorEmailResponse } from 'jslib/models/response/twoFactorEmailResponse'; + +import { TwoFactorBaseComponent } from './two-factor-base.component'; + +@Component({ + selector: 'app-two-factor-email', + templateUrl: 'two-factor-email.component.html', +}) +export class TwoFactorEmailComponent extends TwoFactorBaseComponent { + email: string; + token: string; + sentEmail: string; + formPromise: Promise; + emailPromise: Promise; + + constructor(apiService: ApiService, i18nService: I18nService, + analytics: Angulartics2, toasterService: ToasterService, + platformUtilsService: PlatformUtilsService, private userService: UserService) { + super(apiService, i18nService, analytics, toasterService, platformUtilsService, + TwoFactorProviderType.Email); + } + + auth(authResponse: any) { + super.auth(authResponse); + return this.processResponse(authResponse.response); + } + + submit() { + if (this.enabled) { + return super.disable(this.formPromise); + } else { + return this.enable(); + } + } + + async sendEmail() { + try { + const request = new TwoFactorEmailRequest(this.email, this.masterPasswordHash); + this.emailPromise = this.apiService.postTwoFactorEmailSetup(request); + await this.emailPromise; + this.sentEmail = this.email; + } catch { } + } + + protected enable() { + const request = new UpdateTwoFactorEmailRequest(); + request.masterPasswordHash = this.masterPasswordHash; + request.email = this.email; + request.token = this.token; + + return super.enable(async () => { + this.formPromise = this.apiService.putTwoFactorEmail(request); + const response = await this.formPromise; + await this.processResponse(response); + }); + } + + private async processResponse(response: TwoFactorEmailResponse) { + this.token = null; + this.email = response.email; + this.enabled = response.enabled; + if (!this.enabled && (this.email == null || this.email === '')) { + this.email = await this.userService.getEmail(); + } + } +} diff --git a/src/app/settings/two-factor-recovery.component.html b/src/app/settings/two-factor-recovery.component.html new file mode 100644 index 0000000000..391c2c281c --- /dev/null +++ b/src/app/settings/two-factor-recovery.component.html @@ -0,0 +1,32 @@ + diff --git a/src/app/settings/two-factor-recovery.component.ts b/src/app/settings/two-factor-recovery.component.ts new file mode 100644 index 0000000000..913e263551 --- /dev/null +++ b/src/app/settings/two-factor-recovery.component.ts @@ -0,0 +1,46 @@ +import { Component } from '@angular/core'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { TwoFactorRecoverResponse } from 'jslib/models/response/twoFactorRescoverResponse'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; + +@Component({ + selector: 'app-two-factor-recovery', + templateUrl: 'two-factor-recovery.component.html', +}) +export class TwoFactorRecoveryComponent { + code: string; + authed: boolean; + twoFactorProviderType = TwoFactorProviderType; + + constructor(private i18nService: I18nService) { } + + auth(authResponse: any) { + this.authed = true; + this.processResponse(authResponse.response); + } + + print() { + const w = window.open(); + w.document.write('
' + + '

' + this.i18nService.t('twoFactorRecoveryYourCode') + ':

' + + '' + + this.code + '
' + + '

' + new Date() + '

'); + w.print(); + w.close(); + } + + private formatString(s: string) { + if (s == null) { + return null; + } + return s.replace(/(.{4})/g, '$1 ').trim().toUpperCase(); + } + + private processResponse(response: TwoFactorRecoverResponse) { + this.code = this.formatString(response.code); + } +} diff --git a/src/app/settings/two-factor-setup.component.html b/src/app/settings/two-factor-setup.component.html new file mode 100644 index 0000000000..19ba71d93a --- /dev/null +++ b/src/app/settings/two-factor-setup.component.html @@ -0,0 +1,42 @@ + + +

{{'twoStepLoginRecoveryWarning' | i18n}}

+ +
+

+ {{'providers' | i18n}} + + + +

+ + + + + + + + diff --git a/src/app/settings/two-factor-setup.component.ts b/src/app/settings/two-factor-setup.component.ts new file mode 100644 index 0000000000..32403329b2 --- /dev/null +++ b/src/app/settings/two-factor-setup.component.ts @@ -0,0 +1,153 @@ +import { + Component, + ComponentFactoryResolver, + OnInit, + Type, + ViewChild, + ViewContainerRef, +} from '@angular/core'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { TokenService } from 'jslib/abstractions/token.service'; + +import { TwoFactorProviders } from 'jslib/services/auth.service'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; + +import { ModalComponent } from '../modal.component'; + +import { TwoFactorAuthenticatorComponent } from './two-factor-authenticator.component'; +import { TwoFactorDuoComponent } from './two-factor-duo.component'; +import { TwoFactorEmailComponent } from './two-factor-email.component'; +import { TwoFactorRecoveryComponent } from './two-factor-recovery.component'; +import { TwoFactorU2fComponent } from './two-factor-u2f.component'; +import { TwoFactorYubiKeyComponent } from './two-factor-yubikey.component'; + +@Component({ + selector: 'app-two-factor-setup', + templateUrl: 'two-factor-setup.component.html', +}) +export class TwoFactorSetupComponent implements OnInit { + @ViewChild('recoveryTemplate', { read: ViewContainerRef }) recoveryModalRef: ViewContainerRef; + @ViewChild('authenticatorTemplate', { read: ViewContainerRef }) authenticatorModalRef: ViewContainerRef; + @ViewChild('yubikeyTemplate', { read: ViewContainerRef }) yubikeyModalRef: ViewContainerRef; + @ViewChild('u2fTemplate', { read: ViewContainerRef }) u2fModalRef: ViewContainerRef; + @ViewChild('duoTemplate', { read: ViewContainerRef }) duoModalRef: ViewContainerRef; + @ViewChild('emailTemplate', { read: ViewContainerRef }) emailModalRef: ViewContainerRef; + + providers: any[] = []; + premium: boolean; + loading = true; + + private modal: ModalComponent = null; + + constructor(private apiService: ApiService, private tokenService: TokenService, + private componentFactoryResolver: ComponentFactoryResolver) { } + + async ngOnInit() { + this.premium = this.tokenService.getPremium(); + + for (const key in TwoFactorProviders) { + if (!TwoFactorProviders.hasOwnProperty(key)) { + continue; + } + + const p = (TwoFactorProviders as any)[key]; + if (p.type === TwoFactorProviderType.OrganizationDuo) { + continue; + } + + this.providers.push({ + type: p.type, + name: p.name, + description: p.description, + enabled: false, + premium: p.premium, + sort: p.sort, + }); + } + + this.providers.sort((a: any, b: any) => a.sort - b.sort); + await this.load(); + } + + async load() { + this.loading = true; + const providerList = await this.apiService.getTwoFactorProviders(); + providerList.data.forEach((p) => { + this.providers.forEach((p2) => { + if (p.type === p2.type) { + p2.enabled = p.enabled; + } + }); + }); + this.loading = false; + } + + manage(type: TwoFactorProviderType) { + switch (type) { + case TwoFactorProviderType.Authenticator: + const authComp = this.openModal(this.authenticatorModalRef, TwoFactorAuthenticatorComponent); + authComp.onUpdated.subscribe((enabled: boolean) => { + this.updateStatus(enabled, TwoFactorProviderType.Authenticator); + }); + break; + case TwoFactorProviderType.Yubikey: + const yubiComp = this.openModal(this.yubikeyModalRef, TwoFactorYubiKeyComponent); + yubiComp.onUpdated.subscribe((enabled: boolean) => { + this.updateStatus(enabled, TwoFactorProviderType.Yubikey); + }); + break; + case TwoFactorProviderType.Duo: + const duoComp = this.openModal(this.duoModalRef, TwoFactorDuoComponent); + duoComp.onUpdated.subscribe((enabled: boolean) => { + this.updateStatus(enabled, TwoFactorProviderType.Duo); + }); + break; + case TwoFactorProviderType.Email: + const emailComp = this.openModal(this.emailModalRef, TwoFactorEmailComponent); + emailComp.onUpdated.subscribe((enabled: boolean) => { + this.updateStatus(enabled, TwoFactorProviderType.Email); + }); + break; + case TwoFactorProviderType.U2f: + const u2fComp = this.openModal(this.u2fModalRef, TwoFactorU2fComponent); + u2fComp.onUpdated.subscribe((enabled: boolean) => { + this.updateStatus(enabled, TwoFactorProviderType.U2f); + }); + break; + default: + break; + } + } + + recoveryCode() { + this.openModal(this.recoveryModalRef, TwoFactorRecoveryComponent); + } + + private openModal(ref: ViewContainerRef, type: Type): T { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = ref.createComponent(factory).instance; + const childComponent = this.modal.show(type, ref); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + return childComponent; + } + + private updateStatus(enabled: boolean, type: TwoFactorProviderType) { + if (!enabled && this.modal != null) { + this.modal.close(); + } + this.providers.forEach((p) => { + if (p.type === type) { + p.enabled = enabled; + } + }); + } +} diff --git a/src/app/settings/two-factor-u2f.component.html b/src/app/settings/two-factor-u2f.component.html new file mode 100644 index 0000000000..0204662521 --- /dev/null +++ b/src/app/settings/two-factor-u2f.component.html @@ -0,0 +1,69 @@ + diff --git a/src/app/settings/two-factor-u2f.component.ts b/src/app/settings/two-factor-u2f.component.ts new file mode 100644 index 0000000000..e32cf9d615 --- /dev/null +++ b/src/app/settings/two-factor-u2f.component.ts @@ -0,0 +1,113 @@ +import { + Component, + OnDestroy, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; +import { UpdateTwoFactorU2fRequest } from 'jslib/models/request/updateTwoFactorU2fRequest'; +import { TwoFactorU2fResponse } from 'jslib/models/response/twoFactorU2fResponse'; + +import { TwoFactorBaseComponent } from './two-factor-base.component'; + +@Component({ + selector: 'app-two-factor-u2f', + templateUrl: 'two-factor-u2f.component.html', +}) +export class TwoFactorU2fComponent extends TwoFactorBaseComponent implements OnInit, OnDestroy { + u2fChallenge: any; + u2fError: boolean; + u2fListening: boolean; + u2fResponse: string; + formPromise: Promise; + + private closed = false; + private u2fScript: HTMLScriptElement; + + constructor(apiService: ApiService, i18nService: I18nService, + analytics: Angulartics2, toasterService: ToasterService, + platformUtilsService: PlatformUtilsService) { + super(apiService, i18nService, analytics, toasterService, platformUtilsService, + TwoFactorProviderType.U2f); + this.u2fScript = window.document.createElement('script'); + this.u2fScript.src = 'scripts/u2f.js'; + this.u2fScript.async = true; + } + + ngOnInit() { + window.document.body.appendChild(this.u2fScript); + } + + ngOnDestroy() { + this.closed = true; + window.document.body.removeChild(this.u2fScript); + } + + auth(authResponse: any) { + super.auth(authResponse); + this.processResponse(authResponse.response); + this.readDevice(); + } + + submit() { + if (this.enabled) { + return super.disable(this.formPromise); + } else { + return this.enable(); + } + } + + protected enable() { + const request = new UpdateTwoFactorU2fRequest(); + request.masterPasswordHash = this.masterPasswordHash; + request.deviceResponse = this.u2fResponse; + + return super.enable(async () => { + this.formPromise = this.apiService.putTwoFactorU2f(request); + const response = await this.formPromise; + await this.processResponse(response); + }); + } + + private readDevice() { + if (this.closed || this.enabled) { + return; + } + + // tslint:disable-next-line + console.log('listening for key...'); + + this.u2fResponse = null; + this.u2fError = false; + this.u2fListening = true; + + (window as any).u2f.register(this.u2fChallenge.AppId, [{ + version: this.u2fChallenge.Version, + challenge: this.u2fChallenge.Challenge, + }], [], (data: any) => { + this.u2fListening = false; + if (data.errorCode === 5) { + this.readDevice(); + return; + } else if (data.errorCode) { + this.u2fError = true; + // tslint:disable-next-line + console.log('error: ' + data.errorCode); + return; + } + this.u2fResponse = JSON.stringify(data); + }, 10); + } + + private processResponse(response: TwoFactorU2fResponse) { + this.u2fChallenge = response.challenge; + this.enabled = response.enabled; + } +} diff --git a/src/app/settings/two-factor-verify.component.html b/src/app/settings/two-factor-verify.component.html new file mode 100644 index 0000000000..8681c91e96 --- /dev/null +++ b/src/app/settings/two-factor-verify.component.html @@ -0,0 +1,15 @@ +
+ + +
diff --git a/src/app/settings/two-factor-verify.component.ts b/src/app/settings/two-factor-verify.component.ts new file mode 100644 index 0000000000..5d8ce40bb3 --- /dev/null +++ b/src/app/settings/two-factor-verify.component.ts @@ -0,0 +1,76 @@ +import { + Component, + EventEmitter, + Input, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { PasswordVerificationRequest } from 'jslib/models/request/passwordVerificationRequest'; + +@Component({ + selector: 'app-two-factor-verify', + templateUrl: 'two-factor-verify.component.html', +}) +export class TwoFactorVerifyComponent { + @Input() + type: TwoFactorProviderType; + @Output() + onAuthed = new EventEmitter(); + + masterPassword: string; + formPromise: Promise; + + private masterPasswordHash: string; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private toasterService: ToasterService, private cryptoService: CryptoService) { } + + async submit() { + if (this.masterPassword == null || this.masterPassword === '') { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('masterPassRequired')); + return; + } + + const request = new PasswordVerificationRequest(); + request.masterPasswordHash = this.masterPasswordHash = + await this.cryptoService.hashPassword(this.masterPassword, null); + + try { + switch (this.type) { + case -1: + this.formPromise = this.apiService.getTwoFactorRecover(request); + break; + case TwoFactorProviderType.Duo: + this.formPromise = this.apiService.getTwoFactorDuo(request); + break; + case TwoFactorProviderType.Email: + this.formPromise = this.apiService.getTwoFactorEmail(request); + break; + case TwoFactorProviderType.U2f: + this.formPromise = this.apiService.getTwoFactorU2f(request); + break; + case TwoFactorProviderType.Authenticator: + this.formPromise = this.apiService.getTwoFactorAuthenticator(request); + break; + case TwoFactorProviderType.Yubikey: + this.formPromise = this.apiService.getTwoFactorYubiKey(request); + break; + } + + const response = await this.formPromise; + this.onAuthed.emit({ + response: response, + masterPasswordHash: this.masterPasswordHash, + }); + } catch { } + } +} diff --git a/src/app/settings/two-factor-yubikey.component.html b/src/app/settings/two-factor-yubikey.component.html new file mode 100644 index 0000000000..e9560fc513 --- /dev/null +++ b/src/app/settings/two-factor-yubikey.component.html @@ -0,0 +1,71 @@ + diff --git a/src/app/settings/two-factor-yubikey.component.ts b/src/app/settings/two-factor-yubikey.component.ts new file mode 100644 index 0000000000..efd8015a05 --- /dev/null +++ b/src/app/settings/two-factor-yubikey.component.ts @@ -0,0 +1,89 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { UpdateTwoFactorYubioOtpRequest } from 'jslib/models/request/updateTwoFactorYubioOtpRequest'; +import { TwoFactorYubiKeyResponse } from 'jslib/models/response/twoFactorYubiKeyResponse'; + +import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType'; + +import { TwoFactorBaseComponent } from './two-factor-base.component'; + +@Component({ + selector: 'app-two-factor-yubikey', + templateUrl: 'two-factor-yubikey.component.html', +}) +export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent { + keys: any[]; + nfc = false; + + formPromise: Promise; + disablePromise: Promise; + + constructor(apiService: ApiService, i18nService: I18nService, + analytics: Angulartics2, toasterService: ToasterService, + platformUtilsService: PlatformUtilsService) { + super(apiService, i18nService, analytics, toasterService, platformUtilsService, + TwoFactorProviderType.Yubikey); + } + + auth(authResponse: any) { + super.auth(authResponse); + this.processResponse(authResponse.response); + } + + submit() { + const request = new UpdateTwoFactorYubioOtpRequest(); + request.masterPasswordHash = this.masterPasswordHash; + request.key1 = this.keys != null && this.keys.length > 0 ? this.keys[0].key : null; + request.key2 = this.keys != null && this.keys.length > 1 ? this.keys[1].key : null; + request.key3 = this.keys != null && this.keys.length > 2 ? this.keys[2].key : null; + request.key4 = this.keys != null && this.keys.length > 3 ? this.keys[3].key : null; + request.key5 = this.keys != null && this.keys.length > 4 ? this.keys[4].key : null; + request.nfc = this.nfc; + + return super.enable(async () => { + this.formPromise = this.apiService.putTwoFactorYubiKey(request); + const response = await this.formPromise; + await this.processResponse(response); + this.toasterService.popAsync('success', null, this.i18nService.t('yubikeysUpdated')); + }); + } + + disable() { + return super.disable(this.disablePromise); + } + + remove(key: any) { + key.existingKey = null; + key.key = null; + } + + private processResponse(response: TwoFactorYubiKeyResponse) { + this.enabled = response.enabled; + this.keys = [ + { key: response.key1, existingKey: this.padRight(response.key1) }, + { key: response.key2, existingKey: this.padRight(response.key2) }, + { key: response.key3, existingKey: this.padRight(response.key3) }, + { key: response.key4, existingKey: this.padRight(response.key4) }, + { key: response.key5, existingKey: this.padRight(response.key5) }, + ]; + this.nfc = response.nfc || !response.enabled; + } + + private padRight(str: string, character = '•', size = 44) { + if (str == null || character == null || str.length >= size) { + return str; + } + const max = (size - str.length) / character.length; + for (let i = 0; i < max; i++) { + str += character; + } + return str; + } +} diff --git a/src/app/settings/update-license.component.html b/src/app/settings/update-license.component.html new file mode 100644 index 0000000000..9b67578dda --- /dev/null +++ b/src/app/settings/update-license.component.html @@ -0,0 +1,14 @@ +
+
+ + + {{'licenseFileDesc' | i18n : (user ? 'bitwarden_premium_license.json' : 'bitwarden_organization_license.json')}} +
+ + +
diff --git a/src/app/settings/update-license.component.ts b/src/app/settings/update-license.component.ts new file mode 100644 index 0000000000..338c446b92 --- /dev/null +++ b/src/app/settings/update-license.component.ts @@ -0,0 +1,57 @@ +import { + Component, + EventEmitter, + Input, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +@Component({ + selector: 'app-update-license', + templateUrl: 'update-license.component.html', +}) +export class UpdateLicenseComponent { + @Input() user = true; + @Output() onUpdated = new EventEmitter(); + @Output() onCanceled = new EventEmitter(); + + formPromise: Promise; + + constructor(private apiService: ApiService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService) { } + + async submit() { + const fileEl = document.getElementById('file') as HTMLInputElement; + const files = fileEl.files; + if (files == null || files.length === 0) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('selectFile')); + return; + } + + try { + const fd = new FormData(); + fd.append('license', files[0]); + + if (this.user) { + this.formPromise = this.apiService.postAccountLicense(fd); + } else { + // TODO + } + + await this.formPromise; + this.analytics.eventTrack.next({ action: 'Updated License' }); + this.toasterService.popAsync('success', null, this.i18nService.t('updatedLicense')); + this.onUpdated.emit(); + } catch { } + } + + cancel() { + this.onCanceled.emit(); + } +} diff --git a/src/app/settings/user-billing.component.html b/src/app/settings/user-billing.component.html new file mode 100644 index 0000000000..7f3669455a --- /dev/null +++ b/src/app/settings/user-billing.component.html @@ -0,0 +1,132 @@ + + + + {{'subscriptionCanceled' | i18n}} + +

{{'subscriptionPendingCanceled' | i18n}}

+ +
+
+
{{'expiration' | i18n}}
+
{{billing.expiration | date:'mediumDate'}}
+
{{'neverExpires' | i18n}}
+
+
+
+
+
{{'status' | i18n}}
+
+ {{(subscription && subscription.status) || '-'}} + {{'pendingCancellation' | i18n}} +
+
{{'nextCharge' | i18n}}
+
{{nextInvoice ? ((nextInvoice.date | date: 'mediumDate') + ', ' + (nextInvoice.amount | currency:'$')) : + '-'}} +
+
+
+
+ {{'details' | i18n}} + + + + + + + +
+ {{i.name}} {{i.quantity > 1 ? '×' + i.quantity : ''}} @ {{i.amount | currency:'$'}} + + {{(i.quantity * i.amount) | currency:'$'}} /{{i.interval | i18n}} +
+
+
+ +
+ + + {{'manageSubscription' | i18n}} + +
+
+
+

{{'updateLicense' | i18n}}

+ +
+
+
+ + +
+ + +
+
+

{{'storage' | i18n}}

+

{{'subscriptionStorage' | i18n : billing.maxStorageGb : billing.storageName || '0 MB'}}

+
+
{{(storagePercentage / 100) | percent}}
+
+ +
+ + + + + +
+
+

{{'paymentMethod' | i18n}}

+

{{'noPaymentMethod' | i18n}}

+

+ + {{paymentSource.description}} +

+ + + +

{{'charges' | i18n}}

+

{{'noCharges' | i18n}}

+ + + + + + + + + +
{{c.createdDate | date:'mediumDate'}}{{c.paymentSource ? c.paymentSource.description : '-'}}{{c.status}}{{c.amount | currency:'$'}}
+ * {{'chargesStatement' | i18n : 'BITWARDEN'}} +
+
diff --git a/src/app/settings/user-billing.component.ts b/src/app/settings/user-billing.component.ts new file mode 100644 index 0000000000..09520516e9 --- /dev/null +++ b/src/app/settings/user-billing.component.ts @@ -0,0 +1,175 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { BillingResponse } from 'jslib/models/response/billingResponse'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { TokenService } from 'jslib/abstractions/token.service'; + +import { PaymentMethodType } from 'jslib/enums/paymentMethodType'; + +@Component({ + selector: 'app-user-billing', + templateUrl: 'user-billing.component.html', +}) +export class UserBillingComponent implements OnInit { + loading = false; + firstLoaded = false; + adjustStorageAdd = true; + showAdjustStorage = false; + showAdjustPayment = false; + showUpdateLicense = false; + billing: BillingResponse; + paymentMethodType = PaymentMethodType; + selfHosted = false; + + cancelPromise: Promise; + reinstatePromise: Promise; + + constructor(private tokenService: TokenService, private apiService: ApiService, + private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, + private analytics: Angulartics2, private toasterService: ToasterService, + private router: Router) { + this.selfHosted = platformUtilsService.isSelfHost(); + } + + async ngOnInit() { + await this.load(); + this.firstLoaded = true; + } + + async load() { + if (this.loading) { + return; + } + + const premium = this.tokenService.getPremium(); + if (premium) { + this.loading = true; + this.billing = await this.apiService.getUserBilling(); + } else { + this.router.navigate(['/settings/premium']); + return; + } + + this.loading = false; + } + + async reinstate() { + if (this.loading) { + return; + } + + const confirmed = await this.platformUtilsService.showDialog(this.i18nService.t('reinstateConfirmation'), + this.i18nService.t('reinstateSubscription'), this.i18nService.t('yes'), this.i18nService.t('cancel')); + if (!confirmed) { + return; + } + + try { + this.reinstatePromise = this.apiService.postReinstatePremium(); + await this.reinstatePromise; + this.analytics.eventTrack.next({ action: 'Reinstated Premium' }); + this.toasterService.popAsync('success', null, this.i18nService.t('reinstated')); + this.load(); + } catch { } + } + + async cancel() { + if (this.loading) { + return; + } + + const confirmed = await this.platformUtilsService.showDialog(this.i18nService.t('cancelConfirmation'), + this.i18nService.t('cancelSubscription'), this.i18nService.t('yes'), this.i18nService.t('no'), 'warning'); + if (!confirmed) { + return; + } + + try { + this.cancelPromise = this.apiService.postCancelPremium(); + await this.cancelPromise; + this.analytics.eventTrack.next({ action: 'Canceled Premium' }); + this.toasterService.popAsync('success', null, this.i18nService.t('canceledSubscription')); + this.load(); + } catch { } + } + + downloadLicense() { + if (this.loading) { + return; + } + + const licenseString = JSON.stringify(this.billing.license, null, 2); + this.platformUtilsService.saveFile(window, licenseString, null, 'bitwarden_premium_license.json'); + } + + updateLicense() { + if (this.loading) { + return; + } + this.showUpdateLicense = true; + } + + closeUpdateLicense(load: boolean) { + this.showUpdateLicense = false; + if (load) { + this.load(); + } + } + + adjustStorage(add: boolean) { + this.adjustStorageAdd = add; + this.showAdjustStorage = true; + } + + closeStorage(load: boolean) { + this.showAdjustStorage = false; + if (load) { + this.load(); + } + } + + changePayment() { + this.showAdjustPayment = true; + } + + closePayment(load: boolean) { + this.showAdjustPayment = false; + if (load) { + this.load(); + } + } + + get subscriptionMarkedForCancel() { + return this.subscription != null && !this.subscription.cancelled && this.subscription.cancelAtEndDate; + } + + get subscription() { + return this.billing != null ? this.billing.subscription : null; + } + + get nextInvoice() { + return this.billing != null ? this.billing.upcomingInvoice : null; + } + + get paymentSource() { + return this.billing != null ? this.billing.paymentSource : null; + } + + get charges() { + return this.billing != null ? this.billing.charges : null; + } + + get storagePercentage() { + return this.billing != null ? +(100 * (this.billing.storageGb / this.billing.maxStorageGb)).toFixed(2) : 0; + } +} diff --git a/src/app/settings/views/settings.html b/src/app/settings/views/settings.html deleted file mode 100644 index 1b50ffb5a9..0000000000 --- a/src/app/settings/views/settings.html +++ /dev/null @@ -1,164 +0,0 @@ -
-

- Settings - manage your account -

-
-
-
-
-

General

-
-
-
-
-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- - -
-
- - -
-
- - -
-
-
- -
-
-
- -
-
-
-
-

Master Password

-
-
-
-
-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
- - -
-
-
-
- -
-
-
-
-

Web Vault Options

-
-
-
-
- -

Website Icons provide a recognizable image next to each login item in your vault.

-
-
- -
-
-
-
-

Organizations

-
-
- No organizations yet for your account. -
- - -
-
-
-

Danger Zone

-
-
- Careful, these actions are not reversible! -
- -
-
\ No newline at end of file diff --git a/src/app/settings/views/settingsAddEditEquivalentDomain.html b/src/app/settings/views/settingsAddEditEquivalentDomain.html deleted file mode 100644 index b2fcfbcbbc..0000000000 --- a/src/app/settings/views/settingsAddEditEquivalentDomain.html +++ /dev/null @@ -1,35 +0,0 @@ - -
- - -
\ No newline at end of file diff --git a/src/app/settings/views/settingsBilling.html b/src/app/settings/views/settingsBilling.html deleted file mode 100644 index 5c67d69b31..0000000000 --- a/src/app/settings/views/settingsBilling.html +++ /dev/null @@ -1,178 +0,0 @@ -
-

Billing manage your membership

-
-
-
-

Canceled

- The premium membership subscription has been canceled. -
-
-

Pending Cancellation

-

- The premium membership has been marked for cancellation at the end of the - current billing period. -

- -
-
-
-

Premium Membership

-
-
-
-
Expiration
-
- Loading... -
-
- {{expiration | date: 'medium'}} -
-
- Never expires -
-
-
-
-
-
Status
-
- {{(subscription && subscription.status) || '-'}} - - marked for cancellation -
-
Next Charge
-
{{nextInvoice ? ((nextInvoice.date | date: 'mediumDate') + ', ' + (nextInvoice.amount | currency:'$')) : '-'}}
-
-
-
- Details -
- Loading... -
-
- - - - - - - -
- {{item.name}} {{item.qty > 1 ? '×' + item.qty : ''}} - @ {{item.amount | currency:'$'}} - {{(item.qty * item.amount) | currency:'$'}} /{{item.interval}}
-
-
-
-
- - -
-
-
-

Storage

-
-
-

- Your membership has a total of {{storage.maxGb}} GB of encrypted file storage. - You are currently using {{storage.currentName}}. -

-
-
- {{storage.percentage}}% -
-
-
- -
-
-
-

Payment Method

-
-
-
- Loading... -
-
- No payment method on file. -
-
- - {{paymentSource.description}} -
-
- -
-
-
-

Charges

-
-
-
- Loading... -
-
- No charges. -
-
- - - - - - - - - -
- {{charge.date | date: 'mediumDate'}} - - {{charge.paymentSource}} - - {{charge.status}} - - {{charge.amount | currency:'$'}} -
-
-
- -
-
diff --git a/src/app/settings/views/settingsBillingAdjustStorage.html b/src/app/settings/views/settingsBillingAdjustStorage.html deleted file mode 100644 index 2d2315cfe5..0000000000 --- a/src/app/settings/views/settingsBillingAdjustStorage.html +++ /dev/null @@ -1,46 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsBillingChangePayment.html b/src/app/settings/views/settingsBillingChangePayment.html deleted file mode 100644 index 5e08b09d47..0000000000 --- a/src/app/settings/views/settingsBillingChangePayment.html +++ /dev/null @@ -1,433 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsBillingUpdateLicense.html b/src/app/settings/views/settingsBillingUpdateLicense.html deleted file mode 100644 index d26834d2e5..0000000000 --- a/src/app/settings/views/settingsBillingUpdateLicense.html +++ /dev/null @@ -1,30 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsChangeEmail.html b/src/app/settings/views/settingsChangeEmail.html deleted file mode 100644 index 05c359d21a..0000000000 --- a/src/app/settings/views/settingsChangeEmail.html +++ /dev/null @@ -1,58 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsChangePassword.html b/src/app/settings/views/settingsChangePassword.html deleted file mode 100644 index 0909fedc0e..0000000000 --- a/src/app/settings/views/settingsChangePassword.html +++ /dev/null @@ -1,43 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsCreateOrganization.html b/src/app/settings/views/settingsCreateOrganization.html deleted file mode 100644 index 98a9dd8e7f..0000000000 --- a/src/app/settings/views/settingsCreateOrganization.html +++ /dev/null @@ -1,697 +0,0 @@ -
-

Create Organization

-
-
-

- Organizations allow you to share parts of your vault with others as well as manage related users - for a specific entity (such as a family, small team, or large company). -

-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
-
-
-

License

-
-
-

To create an on-premise hosted organization you need to upload a valid license file.

-
- - -

- Your license file will be named something like bitwarden_organization_license.json -

-
-
- -
-
-
-
-
-

General Information

-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- -
-
-
-
- - -
-
-
-
-
-
-
-

Choose Your Plan

-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Additional Users (Seats)

-
-
-

- Your plan comes with {{plans[model.plan].baseSeats}} users (seats). You can add additional users - - (up to {{plans[model.plan].maxAdditionalSeats}} more) - - for {{plans[model.plan].seatPrice | currency:'$'}} per user /month. -

-
-
-
- - -
-
-
-
-
-
-
-

Users (Seats)

-
-
-

- How many user seats do you need? - You can also add additional seats later if needed. -

-
-
-
- - -
-
-
-
-
-
-
-

Additional Storage

-
-
-
-

- Your plan comes with 1 GB of encrypted file storage. You can add additional - storage for {{storageGb.price | currency:"$":2}} per GB /month. -

-
-
- - -
-
-
-
-
-
-
-

Billing Summary

-
-
-
- -
-
- -
-
- -
-
-
-

Payment Information

-
-
- - -
-
-
-

You must verify your bank account

-

- Payment with a bank account is only available to customers in the United States. - You will be required to verify your bank account. We will make two micro-deposits within the next - 1-2 business days. Enter these amounts in the organization's billing area to verify the bank account. - Failure to verify the bank account will result in a missed payment and your organization being - disabled. -

-
-
-
-
- - -
-
-
-
- - -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
-
-
-
-
- - -
-
-
- -
    -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- -
-
-
-
diff --git a/src/app/settings/views/settingsDelete.html b/src/app/settings/views/settingsDelete.html deleted file mode 100644 index aac207e99d..0000000000 --- a/src/app/settings/views/settingsDelete.html +++ /dev/null @@ -1,30 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsDomains.html b/src/app/settings/views/settingsDomains.html deleted file mode 100644 index 9bfe501ce9..0000000000 --- a/src/app/settings/views/settingsDomains.html +++ /dev/null @@ -1,117 +0,0 @@ -
-

Domain Rules

-
-
-

- If you have the same login across multiple different website domains, you can mark the website as "equivalent". - "Global" domains are ones already created for you by Bitwarden. -

-
-
-
-

Custom

-
- -
-
-
-
- - - - - - - - - - - - -
-
- - -
-
{{customDomain}}
No domains to list.
-
-
- -
-
- -
-
-
-

Global

-
-
-
- - - - - - - - - - - - -
-
- - -
-
{{::globalDomain.domains}}
No domains to list.
-
-
- -
-
-
- diff --git a/src/app/settings/views/settingsPremium.html b/src/app/settings/views/settingsPremium.html deleted file mode 100644 index 95a210e784..0000000000 --- a/src/app/settings/views/settingsPremium.html +++ /dev/null @@ -1,487 +0,0 @@ -
-

Premiumget started today!

-
-
-
-
-

Errors have occurred

-
    -
  • {{e}}
  • -
-
-
-
-
-
-

Sign up for a premium membership and get:

-
    -
  • - - 1 GB of encrypted file storage. -
  • -
  • - - Additional two-step login options such as YubiKey, FIDO U2F, and Duo. -
  • -
  • - - TOTP verification code (2FA) generator for logins in your vault. -
  • -
  • - - Priority customer support. -
  • -
  • - - All future premium features. More coming soon! -
  • -
-
-
- all for just
- {{premiumPrice | currency:"$":0}} /year -
-
-
- -
-
-
-
-

License

-
-
-

To upgrade your account to a premium membership you need to upload a valid license file.

-
- - -

- Your license file will be named something like bitwarden_premium_license.json -

-
-
- -
-
-
-
-
-

Addons

-
-
-
- -

- Your plan comes with 1 GB of encrypted file storage. You can add additional - storage for {{storageGbPrice | currency:"$":0}} per GB /year. -

-
-
- -
-
-
-
-
-
-
-

Billing Summary

-
-
- Premium membership: - {{premiumPrice | currency:"$"}}
- Additional storage: - {{model.additionalStorageGb || 0}} GB × {{storageGbPrice | currency:"$"}} = - {{(model.additionalStorageGb || 0) * storageGbPrice | currency:"$"}} -
- -
-
-
-

Payment Information

-
-
- - -
-
-
-
-
-
-
-
- - -
-
-
- -
    -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- -
-
-
-
diff --git a/src/app/settings/views/settingsPurge.html b/src/app/settings/views/settingsPurge.html deleted file mode 100644 index b73d7738c0..0000000000 --- a/src/app/settings/views/settingsPurge.html +++ /dev/null @@ -1,33 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsSessions.html b/src/app/settings/views/settingsSessions.html deleted file mode 100644 index 5f612a36eb..0000000000 --- a/src/app/settings/views/settingsSessions.html +++ /dev/null @@ -1,37 +0,0 @@ - -
- - -
diff --git a/src/app/settings/views/settingsTwoStep.html b/src/app/settings/views/settingsTwoStep.html deleted file mode 100644 index 799f6571e7..0000000000 --- a/src/app/settings/views/settingsTwoStep.html +++ /dev/null @@ -1,52 +0,0 @@ -
-

Two-step Login secure your account

-
-
-
-
-

Recovery Code

-
-
- The recovery code allows you to access your account in the event that you can no longer use your normal - two-step login provider (ex. you lose your device). Bitwarden support will not be able to assist you if you lose - access to your account. We recommend you write down or print the recovery code and keep it in a safe place. -
- -
-
-
-

Providers

-
-
-
- - - - - - - - -
- - {{::provider.name}} - - - - {{::provider.name}} - PREMIUM - -
{{::provider.description}}
-
- - {{provider.enabled ? 'Enabled' : 'Disabled'}} - -
-
-
-
-
diff --git a/src/app/settings/views/settingsTwoStepAuthenticator.html b/src/app/settings/views/settingsTwoStepAuthenticator.html deleted file mode 100644 index 29d8f0e430..0000000000 --- a/src/app/settings/views/settingsTwoStepAuthenticator.html +++ /dev/null @@ -1,116 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsTwoStepDuo.html b/src/app/settings/views/settingsTwoStepDuo.html deleted file mode 100644 index b93cbcd069..0000000000 --- a/src/app/settings/views/settingsTwoStepDuo.html +++ /dev/null @@ -1,76 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsTwoStepEmail.html b/src/app/settings/views/settingsTwoStepEmail.html deleted file mode 100644 index 82331652f3..0000000000 --- a/src/app/settings/views/settingsTwoStepEmail.html +++ /dev/null @@ -1,77 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsTwoStepRecover.html b/src/app/settings/views/settingsTwoStepRecover.html deleted file mode 100644 index 82b6a84d6b..0000000000 --- a/src/app/settings/views/settingsTwoStepRecover.html +++ /dev/null @@ -1,48 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsTwoStepU2f.html b/src/app/settings/views/settingsTwoStepU2f.html deleted file mode 100644 index 1a2e3cffcc..0000000000 --- a/src/app/settings/views/settingsTwoStepU2f.html +++ /dev/null @@ -1,93 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsTwoStepYubi.html b/src/app/settings/views/settingsTwoStepYubi.html deleted file mode 100644 index d9e9200400..0000000000 --- a/src/app/settings/views/settingsTwoStepYubi.html +++ /dev/null @@ -1,127 +0,0 @@ - -
- - -
-
- - -
diff --git a/src/app/settings/views/settingsUpdateKey.html b/src/app/settings/views/settingsUpdateKey.html deleted file mode 100644 index d72523f0e4..0000000000 --- a/src/app/settings/views/settingsUpdateKey.html +++ /dev/null @@ -1,47 +0,0 @@ - -
- - -
diff --git a/src/app/tools/breach-report.component.html b/src/app/tools/breach-report.component.html new file mode 100644 index 0000000000..a15719372f --- /dev/null +++ b/src/app/tools/breach-report.component.html @@ -0,0 +1,57 @@ + +

{{'breachDesc' | i18n}}

+
+
+
+ + + {{'breachCheckUsernameEmail' | i18n}} +
+
+ +
+
+

{{'reportError' | i18n}}...

+ + + {{'breachUsernameNotFound' | i18n : checkedUsername}} + + + {{'breachUsernameFound' | i18n : checkedUsername : breachedAccounts.length}} + +
    +
  • +
    +
    + +
    +
    +

    {{a.title}}

    +

    +

    {{'compromisedData' | i18n}}:

    +
      +
    • {{d}}
    • +
    +
    +
    +
    +
    {{'website' | i18n}}
    +
    {{a.domain}}
    +
    {{'affectedUsers' | i18n}}
    +
    {{a.pwnCount | number}}
    +
    {{'breachOccurred' | i18n}}
    +
    {{a.breachDate | date: 'mediumDate'}}
    +
    {{'breachReported' | i18n}}
    +
    {{a.addedDate | date: 'mediumDate'}}
    +
    +
    +
    +
  • +
+
+
diff --git a/src/app/tools/breach-report.component.ts b/src/app/tools/breach-report.component.ts new file mode 100644 index 0000000000..8efddd950a --- /dev/null +++ b/src/app/tools/breach-report.component.ts @@ -0,0 +1,38 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { AuditService } from 'jslib/abstractions/audit.service'; +import { UserService } from 'jslib/abstractions/user.service'; +import { BreachAccountResponse } from 'jslib/models/response/breachAccountResponse'; + +@Component({ + selector: 'app-breach-report', + templateUrl: 'breach-report.component.html', +}) +export class BreachReportComponent implements OnInit { + error = false; + username: string; + checkedUsername: string; + breachedAccounts: BreachAccountResponse[] = []; + formPromise: Promise; + + constructor(private auditService: AuditService, private userService: UserService) { } + + async ngOnInit() { + this.username = await this.userService.getEmail(); + } + + async submit() { + this.error = false; + this.username = this.username.toLowerCase(); + try { + this.formPromise = this.auditService.breachedAccounts(this.username); + this.breachedAccounts = await this.formPromise; + } catch { + this.error = true; + } + this.checkedUsername = this.username; + } +} diff --git a/src/app/tools/export.component.html b/src/app/tools/export.component.html new file mode 100644 index 0000000000..a5f0319021 --- /dev/null +++ b/src/app/tools/export.component.html @@ -0,0 +1,17 @@ +
+ +

{{'exportMasterPassword' | i18n}}

+ {{'exportWarning' | i18n}} +
+
+ + +
+
+ +
diff --git a/src/app/tools/export.component.ts b/src/app/tools/export.component.ts new file mode 100644 index 0000000000..5575088a17 --- /dev/null +++ b/src/app/tools/export.component.ts @@ -0,0 +1,32 @@ +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { Component } from '@angular/core'; + +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { ExportService } from 'jslib/abstractions/export.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { ExportComponent as BaseExportComponent } from 'jslib/angular/components/export.component'; + +@Component({ + selector: 'app-export', + templateUrl: 'export.component.html', +}) +export class ExportComponent extends BaseExportComponent { + constructor(analytics: Angulartics2, toasterService: ToasterService, + cryptoService: CryptoService, userService: UserService, + i18nService: I18nService, platformUtilsService: PlatformUtilsService, + exportService: ExportService) { + super(analytics, toasterService, cryptoService, userService, i18nService, platformUtilsService, + exportService, window); + } + + protected saved() { + super.saved(); + this.masterPassword = null; + this.toasterService.popAsync('success', null, this.i18nService.t('exportSuccess')); + } +} diff --git a/src/app/tools/import.component.html b/src/app/tools/import.component.html new file mode 100644 index 0000000000..b50fc50cd2 --- /dev/null +++ b/src/app/tools/import.component.html @@ -0,0 +1,55 @@ + +
+
+
+
+ + +
+
+
+ + + See detailed instructions on our help site at + https://help.bitwarden.com/article/export-your-data/ + + + See detailed instructions on our help site at + https://help.bitwarden.com/article/import-from-lastpass/ + + + Using the KeePassX desktop application, navigate to "Database" → "Export to CSV file" and save the CSV file. + + + In the Avira web vault, go to "Settings" → "My Data" → "Export data" and save the CSV file. + + + In the Blur web vault, click your username at the top and go to "Settings" → "Export Data", then click "Export CSV" + for your "Accounts". + + +
+
+
+ + +
+
+
+
+ + +
+ +
diff --git a/src/app/tools/import.component.ts b/src/app/tools/import.component.ts new file mode 100644 index 0000000000..8398b83990 --- /dev/null +++ b/src/app/tools/import.component.ts @@ -0,0 +1,264 @@ +import { + Component, + OnInit, +} from '@angular/core'; +import { Router } from '@angular/router'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { ApiService } from 'jslib/abstractions/api.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { ImportResult } from 'jslib/models/domain/importResult'; + +import { CipherRequest } from 'jslib/models/request/cipherRequest'; +import { FolderRequest } from 'jslib/models/request/folderRequest'; +import { ImportCiphersRequest } from 'jslib/models/request/importCiphersRequest'; +import { KvpRequest } from 'jslib/models/request/kvpRequest'; + +import { CipherView } from 'jslib/models/view/cipherView'; + +import { AviraCsvImporter } from 'jslib/importers/aviraCsvImporter'; +import { BitwardenCsvImporter } from 'jslib/importers/bitwardenCsvImporter'; +import { BlurCsvImporter } from 'jslib/importers/blurCsvImporter'; +import { Importer } from 'jslib/importers/importer'; +import { KeePassXCsvImporter } from 'jslib/importers/keepassxCsvImporter'; +import { LastPassCsvImporter } from 'jslib/importers/lastpassCsvImporter'; +import { SafeInCloudXmlImporter } from 'jslib/importers/safeInCloudXmlImporter'; + +@Component({ + selector: 'app-import', + templateUrl: 'import.component.html', +}) +export class ImportComponent implements OnInit { + featuredImportOptions: any[]; + importOptions: any[]; + format: string = null; + fileContents: string; + formPromise: Promise; + + protected successNavigate: any[] = ['vault']; + + constructor(protected i18nService: I18nService, protected analytics: Angulartics2, + protected toasterService: ToasterService, protected cipherService: CipherService, + protected folderService: FolderService, protected apiService: ApiService, + protected router: Router) { + } + + ngOnInit() { + this.setImportOptions(); + this.importOptions.sort((a, b) => { + if (a.name == null && b.name != null) { + return -1; + } + if (a.name != null && b.name == null) { + return 1; + } + if (a.name == null && b.name == null) { + return 0; + } + + return this.i18nService.collator ? this.i18nService.collator.compare(a.name, b.name) : + a.name.localeCompare(b.name); + }); + } + + async submit() { + const importer = this.getImporter(); + if (importer === null) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('selectFormat')); + return; + } + + const fileEl = document.getElementById('file') as HTMLInputElement; + const files = fileEl.files; + if ((files == null || files.length === 0) && (this.fileContents == null || this.fileContents === '')) { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('selectFile')); + return; + } + + let fileContents = this.fileContents; + if (files != null && files.length > 0) { + try { + const content = await this.getFileContents(files[0]); + if (content != null) { + fileContents = content; + } + } catch { } + } + + if (fileContents == null || fileContents === '') { + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('selectFile')); + return; + } + + const importResult = await importer.parse(fileContents); + if (importResult.success) { + if (importResult.folders.length === 0 && importResult.ciphers.length === 0) { + this.error(this.i18nService.t('importNothingError')); + return; + } else if (importResult.ciphers.length > 0) { + const halfway = Math.floor(importResult.ciphers.length / 2); + const last = importResult.ciphers.length - 1; + if (this.badData(importResult.ciphers[0]) && this.badData(importResult.ciphers[halfway]) && + this.badData(importResult.ciphers[last])) { + this.error(this.i18nService.t('importFormatError')); + return; + } + } + + try { + this.formPromise = this.postImport(importResult); + await this.formPromise; + this.analytics.eventTrack.next({ + action: 'Imported Data', + properties: { label: this.format }, + }); + this.toasterService.popAsync('success', null, this.i18nService.t('importSuccess')); + this.router.navigate(this.successNavigate); + } catch { } + } else { + this.error(this.i18nService.t('importFormatError')); + } + } + + getFormatInstructionTitle() { + if (this.format == null) { + return null; + } + + const results = this.featuredImportOptions.concat(this.importOptions).filter((o) => o.id === this.format); + if (results.length > 0) { + return this.i18nService.t('instructionsFor', results[0].name); + } + return null; + } + + protected async postImport(importResult: ImportResult) { + const request = new ImportCiphersRequest(); + for (let i = 0; i < importResult.ciphers.length; i++) { + const c = await this.cipherService.encrypt(importResult.ciphers[i]); + request.ciphers.push(new CipherRequest(c)); + } + if (importResult.folders != null) { + for (let i = 0; i < importResult.folders.length; i++) { + const f = await this.folderService.encrypt(importResult.folders[i]); + request.folders.push(new FolderRequest(f)); + } + } + if (importResult.folderRelationships != null) { + importResult.folderRelationships.forEach((v: number, k: number) => + request.folderRelationships.push(new KvpRequest(k, v))); + } + return await this.apiService.postImportCiphers(request); + } + + protected setImportOptions() { + this.featuredImportOptions = [ + { id: null, name: '-- ' + this.i18nService.t('select') + ' --' }, + { id: 'bitwardencsv', name: 'Bitwarden (csv)' }, + { id: 'lastpasscsv', name: 'LastPass (csv)' }, + { id: 'chromecsv', name: 'Chrome (csv)' }, + { id: 'firefoxcsv', name: 'Firefox (csv)' }, + { id: 'keepass2xml', name: 'KeePass 2 (xml)' }, + { id: '1password1pif', name: '1Password (1pif)' }, + { id: 'dashlanecsv', name: 'Dashlane (csv)' }, + ]; + + this.importOptions = [ + { id: 'keepassxcsv', name: 'KeePassX (csv)' }, + { id: '1password6wincsv', name: '1Password 6 Windows (csv)' }, + { id: 'roboformcsv', name: 'RoboForm (csv)' }, + { id: 'keepercsv', name: 'Keeper (csv)' }, + { id: 'enpasscsv', name: 'Enpass (csv)' }, + { id: 'safeincloudxml', name: 'SafeInCloud (xml)' }, + { id: 'pwsafexml', name: 'Password Safe (xml)' }, + { id: 'stickypasswordxml', name: 'Sticky Password (xml)' }, + { id: 'msecurecsv', name: 'mSecure (csv)' }, + { id: 'truekeycsv', name: 'True Key (csv)' }, + { id: 'passwordbossjson', name: 'Password Boss (json)' }, + { id: 'zohovaultcsv', name: 'Zoho Vault (csv)' }, + { id: 'splashidcsv', name: 'SplashID (csv)' }, + { id: 'passworddragonxml', name: 'Password Dragon (xml)' }, + { id: 'padlockcsv', name: 'Padlock (csv)' }, + { id: 'clipperzhtml', name: 'Clipperz (html)' }, + { id: 'aviracsv', name: 'Avira (csv)' }, + { id: 'saferpasscsv', name: 'SaferPass (csv)' }, + { id: 'upmcsv', name: 'Universal Password Manager (csv)' }, + { id: 'ascendocsv', name: 'Ascendo DataVault (csv)' }, + { id: 'meldiumcsv', name: 'Meldium (csv)' }, + { id: 'passkeepcsv', name: 'PassKeep (csv)' }, + { id: 'operacsv', name: 'Opera (csv)' }, + { id: 'vivaldicsv', name: 'Vivaldi (csv)' }, + { id: 'gnomejson', name: 'GNOME Passwords and Keys/Seahorse (json)' }, + { id: 'blurcsv', name: 'Blur (csv)' }, + ]; + } + + protected getImporter(): Importer { + if (this.format == null || this.format === '') { + return null; + } + + switch (this.format) { + case 'bitwardencsv': + return new BitwardenCsvImporter(); + case 'lastpasscsv': + return new LastPassCsvImporter(); + case 'keepassxcsv': + return new KeePassXCsvImporter(); + case 'aviracsv': + return new AviraCsvImporter(); + case 'blurcsv': + return new BlurCsvImporter(); + case 'safeincloudxml': + return new SafeInCloudXmlImporter(); + default: + return null; + } + } + + private error(errorMessage: string) { + this.analytics.eventTrack.next({ + action: 'Import Data Failed', + properties: { label: this.format }, + }); + this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), errorMessage); + } + + private getFileContents(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsText(file, 'utf-8'); + reader.onload = (evt) => { + if (this.format === 'lastpasscsv' && file.type === 'text/html') { + const parser = new DOMParser(); + const doc = parser.parseFromString(evt.target.result, 'text/html'); + const pre = doc.querySelector('pre'); + if (pre != null) { + resolve(pre.textContent); + return; + } + reject(); + return; + } + + resolve(evt.target.result); + }; + reader.onerror = () => { + reject(); + }; + }); + } + + private badData(c: CipherView) { + return (c.name == null || c.name === '--') && + (c.login != null && (c.login.password == null || c.login.password === '')); + } +} diff --git a/src/app/tools/password-generator-history.component.html b/src/app/tools/password-generator-history.component.html new file mode 100644 index 0000000000..5eed695725 --- /dev/null +++ b/src/app/tools/password-generator-history.component.html @@ -0,0 +1,38 @@ + diff --git a/src/app/tools/password-generator-history.component.ts b/src/app/tools/password-generator-history.component.ts new file mode 100644 index 0000000000..e1d47a41f8 --- /dev/null +++ b/src/app/tools/password-generator-history.component.ts @@ -0,0 +1,24 @@ +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { Component } from '@angular/core'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { + PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryComponent, +} from 'jslib/angular/components/password-generator-history.component'; + +@Component({ + selector: 'app-password-generator-history', + templateUrl: 'password-generator-history.component.html', +}) +export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHistoryComponent { + constructor(passwordGenerationService: PasswordGenerationService, analytics: Angulartics2, + platformUtilsService: PlatformUtilsService, i18nService: I18nService, + toasterService: ToasterService) { + super(passwordGenerationService, analytics, platformUtilsService, i18nService, toasterService, window); + } +} diff --git a/src/app/tools/password-generator.component.html b/src/app/tools/password-generator.component.html new file mode 100644 index 0000000000..de6c32b2d2 --- /dev/null +++ b/src/app/tools/password-generator.component.html @@ -0,0 +1,60 @@ + +
+
+ {{password}} +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ +
+
+ diff --git a/src/app/tools/password-generator.component.ts b/src/app/tools/password-generator.component.ts new file mode 100644 index 0000000000..c541eabd2c --- /dev/null +++ b/src/app/tools/password-generator.component.ts @@ -0,0 +1,50 @@ +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { + Component, + ComponentFactoryResolver, + ViewChild, + ViewContainerRef, +} from '@angular/core'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { + PasswordGeneratorComponent as BasePasswordGeneratorComponent, +} from 'jslib/angular/components/password-generator.component'; + +import { ModalComponent } from '../modal.component'; +import { PasswordGeneratorHistoryComponent } from './password-generator-history.component'; + +@Component({ + selector: 'app-password-generator', + templateUrl: 'password-generator.component.html', +}) +export class PasswordGeneratorComponent extends BasePasswordGeneratorComponent { + @ViewChild('historyTemplate', { read: ViewContainerRef }) historyModalRef: ViewContainerRef; + + private modal: ModalComponent = null; + + constructor(passwordGenerationService: PasswordGenerationService, analytics: Angulartics2, + platformUtilsService: PlatformUtilsService, i18nService: I18nService, + toasterService: ToasterService, private componentFactoryResolver: ComponentFactoryResolver) { + super(passwordGenerationService, analytics, platformUtilsService, i18nService, toasterService, window); + } + + history() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.historyModalRef.createComponent(factory).instance; + this.modal.show(PasswordGeneratorHistoryComponent, this.historyModalRef); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } +} diff --git a/src/app/tools/tools.component.html b/src/app/tools/tools.component.html new file mode 100644 index 0000000000..d04ea0b9ff --- /dev/null +++ b/src/app/tools/tools.component.html @@ -0,0 +1,31 @@ + diff --git a/src/app/tools/tools.component.ts b/src/app/tools/tools.component.ts new file mode 100644 index 0000000000..d5ffd9f356 --- /dev/null +++ b/src/app/tools/tools.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-tools', + templateUrl: 'tools.component.html', +}) +export class ToolsComponent { } diff --git a/src/app/tools/toolsController.js b/src/app/tools/toolsController.js deleted file mode 100644 index fba3fe8833..0000000000 --- a/src/app/tools/toolsController.js +++ /dev/null @@ -1,20 +0,0 @@ -angular - .module('bit.tools') - - .controller('toolsController', function ($scope, $uibModal, apiService, toastr, authService) { - $scope.import = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/tools/views/toolsImport.html', - controller: 'toolsImportController' - }); - }; - - $scope.export = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/tools/views/toolsExport.html', - controller: 'toolsExportController' - }); - }; - }); diff --git a/src/app/tools/toolsExportController.js b/src/app/tools/toolsExportController.js deleted file mode 100644 index 5d6aa0bd3a..0000000000 --- a/src/app/tools/toolsExportController.js +++ /dev/null @@ -1,145 +0,0 @@ -angular - .module('bit.tools') - - .controller('toolsExportController', function ($scope, apiService, $uibModalInstance, cipherService, $q, - toastr, $analytics, constants) { - $analytics.eventTrack('toolsExportController', { category: 'Modal' }); - $scope.export = function (model) { - $scope.startedExport = true; - var decCiphers = [], - decFolders = []; - - var folderPromise = apiService.folders.list({}, function (folders) { - decFolders = cipherService.decryptFolders(folders.Data); - }).$promise; - - var ciphersPromise = apiService.ciphers.list({}, function (ciphers) { - decCiphers = cipherService.decryptCiphers(ciphers.Data); - }).$promise; - - $q.all([folderPromise, ciphersPromise]).then(function () { - if (!decCiphers.length) { - toastr.error('Nothing to export.', 'Error!'); - $scope.close(); - return; - } - - var foldersDict = {}; - for (var i = 0; i < decFolders.length; i++) { - foldersDict[decFolders[i].id] = decFolders[i]; - } - - try { - var exportCiphers = []; - for (i = 0; i < decCiphers.length; i++) { - // only export logins and secure notes - if (decCiphers[i].type !== constants.cipherType.login && - decCiphers[i].type !== constants.cipherType.secureNote) { - continue; - } - - var cipher = { - folder: decCiphers[i].folderId && (decCiphers[i].folderId in foldersDict) ? - foldersDict[decCiphers[i].folderId].name : null, - favorite: decCiphers[i].favorite ? 1 : null, - type: null, - name: decCiphers[i].name, - notes: decCiphers[i].notes, - fields: null, - // Login props - login_uri: null, - login_username: null, - login_password: null, - login_totp: null - }; - - var j; - if (decCiphers[i].fields) { - for (j = 0; j < decCiphers[i].fields.length; j++) { - if (!cipher.fields) { - cipher.fields = ''; - } - else { - cipher.fields += '\n'; - } - - cipher.fields += ((decCiphers[i].fields[j].name || '') + ': ' + decCiphers[i].fields[j].value); - } - } - - switch (decCiphers[i].type) { - case constants.cipherType.login: - cipher.type = 'login'; - cipher.login_username = decCiphers[i].login.username; - cipher.login_password = decCiphers[i].login.password; - cipher.login_totp = decCiphers[i].login.totp; - - if (decCiphers[i].login.uris && decCiphers[i].login.uris.length) { - cipher.login_uri = []; - for (j = 0; j < decCiphers[i].login.uris.length; j++) { - cipher.login_uri.push(decCiphers[i].login.uris[j].uri); - } - } - break; - case constants.cipherType.secureNote: - cipher.type = 'note'; - break; - default: - continue; - } - - exportCiphers.push(cipher); - } - - var csvString = Papa.unparse(exportCiphers); - var csvBlob = new Blob([csvString]); - - // IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx - if (window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveBlob(csvBlob, makeFileName()); - } - else { - var a = window.document.createElement('a'); - a.href = window.URL.createObjectURL(csvBlob, { type: 'text/plain' }); - a.download = makeFileName(); - document.body.appendChild(a); - // IE: "Access is denied". - // ref: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access - a.click(); - document.body.removeChild(a); - } - - $analytics.eventTrack('Exported Data'); - toastr.success('Your data has been exported. Check your browser\'s downloads folder.', 'Success!'); - $scope.close(); - } - catch (err) { - toastr.error('Something went wrong. Please try again.', 'Error!'); - $scope.close(); - } - }, function () { - toastr.error('Something went wrong. Please try again.', 'Error!'); - $scope.close(); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - function makeFileName() { - var now = new Date(); - var dateString = - now.getFullYear() + '' + padNumber(now.getMonth() + 1, 2) + '' + padNumber(now.getDate(), 2) + - padNumber(now.getHours(), 2) + '' + padNumber(now.getMinutes(), 2) + - padNumber(now.getSeconds(), 2); - - return 'bitwarden_export_' + dateString + '.csv'; - } - - function padNumber(number, width, paddingCharacter) { - paddingCharacter = paddingCharacter || '0'; - number = number + ''; - return number.length >= width ? number : new Array(width - number.length + 1).join(paddingCharacter) + number; - } - }); diff --git a/src/app/tools/toolsImportController.js b/src/app/tools/toolsImportController.js deleted file mode 100644 index 39f5352398..0000000000 --- a/src/app/tools/toolsImportController.js +++ /dev/null @@ -1,344 +0,0 @@ -angular - .module('bit.tools') - - .controller('toolsImportController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, - toastr, importService, $analytics, $sce, validationService) { - $analytics.eventTrack('toolsImportController', { category: 'Modal' }); - $scope.model = { source: '' }; - $scope.source = {}; - $scope.splitFeatured = true; - - $scope.options = [ - { - id: 'bitwardencsv', - name: 'Bitwarden (csv)', - featured: true, - sort: 1, - instructions: $sce.trustAsHtml('Export using the web vault (vault.bitwarden.com). ' + - 'Log into the web vault and navigate to "Tools" > "Export".') - }, - { - id: 'lastpass', - name: 'LastPass (csv)', - featured: true, - sort: 2, - instructions: $sce.trustAsHtml('See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-lastpass/') - }, - { - id: 'chromecsv', - name: 'Chrome (csv)', - featured: true, - sort: 3, - instructions: $sce.trustAsHtml('See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-chrome/') - }, - { - id: 'firefoxpasswordexportercsv', - name: 'Firefox Password Exporter (csv)', - featured: true, - sort: 4, - instructions: $sce.trustAsHtml('Use the ' + - '' + - 'FF Password Exporter application to export your passwords to a CSV file.') - }, - { - id: 'keepass2xml', - name: 'KeePass 2 (xml)', - featured: true, - sort: 5, - instructions: $sce.trustAsHtml('Using the KeePass 2 desktop application, navigate to "File" > "Export" and ' + - 'select the KeePass XML (2.x) option.') - }, - { - id: 'keepassxcsv', - name: 'KeePassX (csv)', - instructions: $sce.trustAsHtml('Using the KeePassX desktop application, navigate to "Database" > ' + - '"Export to CSV file" and save the CSV file.') - }, - { - id: 'dashlanecsv', - name: 'Dashlane (csv)', - featured: true, - sort: 7, - instructions: $sce.trustAsHtml('Using the Dashlane desktop application, navigate to "File" > "Export" > ' + - '"Unsecured archive (readable) in CSV format" and save the CSV file.') - }, - { - id: '1password1pif', - name: '1Password (1pif)', - featured: true, - sort: 6, - instructions: $sce.trustAsHtml('See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-1password/') - }, - { - id: '1password6wincsv', - name: '1Password 6 Windows (csv)', - instructions: $sce.trustAsHtml('See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-1password/') - }, - { - id: 'roboformhtml', - name: 'RoboForm (html)', - instructions: $sce.trustAsHtml('Using the RoboForm Editor desktop application, navigate to "RoboForm" ' + - '(top left) > "Print List" > "Logins". When the following print dialog pops up click on the "Save" button ' + - 'and save the HTML file.') - }, - { - id: 'keepercsv', - name: 'Keeper (csv)', - instructions: $sce.trustAsHtml('Log into the Keeper web vault (keepersecurity.com/vault). Navigate to "Backup" ' + - '(top right) and find the "Export to Text File" option. Click "Export Now" to save the TXT/CSV file.') - }, - { - id: 'enpasscsv', - name: 'Enpass (csv)', - instructions: $sce.trustAsHtml('Using the Enpass desktop application, navigate to "File" > "Export" > ' + - '"As CSV". Select "Yes" to the warning alert and save the CSV file. Note that the importer only fully ' + - 'supports files exported while Enpass is set to the English language, so adjust your settings accordingly.') - }, - { - id: 'safeincloudxml', - name: 'SafeInCloud (xml)', - instructions: $sce.trustAsHtml('Using the SaveInCloud desktop application, navigate to "File" > "Export" > ' + - '"As XML" and save the XML file.') - }, - { - id: 'pwsafexml', - name: 'Password Safe (xml)', - instructions: $sce.trustAsHtml('Using the Password Safe desktop application, navigate to "File" > ' + - '"Export To" > "XML format..." and save the XML file.') - }, - { - id: 'stickypasswordxml', - name: 'Sticky Password (xml)', - instructions: $sce.trustAsHtml('Using the Sticky Password desktop application, navigate to "Menu" ' + - '(top right) > "Export" > "Export all". Select the unencrypted format XML option and then the ' + - '"Save to file" button. Save the XML file.') - }, - { - id: 'msecurecsv', - name: 'mSecure (csv)', - instructions: $sce.trustAsHtml('Using the mSecure desktop application, navigate to "File" > ' + - '"Export" > "CSV File..." and save the CSV file.') - }, - { - id: 'truekeycsv', - name: 'True Key (csv)', - instructions: $sce.trustAsHtml('Using the True Key desktop application, click the gear icon (top right) and ' + - 'then navigate to "App Settings". Click the "Export" button, enter your password and save the CSV file.') - }, - { - id: 'passwordbossjson', - name: 'Password Boss (json)', - instructions: $sce.trustAsHtml('Using the Password Boss desktop application, navigate to "File" > ' + - '"Export data" > "Password Boss JSON - not encrypted" and save the JSON file.') - }, - { - id: 'zohovaultcsv', - name: 'Zoho Vault (csv)', - instructions: $sce.trustAsHtml('Log into the Zoho web vault (vault.zoho.com). Navigate to "Tools" > ' + - '"Export Secrets". Select "All Secrets" and click the "Zoho Vault Format CSV" button. Highlight ' + - 'and copy the data from the textarea. Open a text editor like Notepad and paste the data. Save the ' + - 'data from the text editor as zoho_export.csv.') - }, - { - id: 'splashidcsv', - name: 'SplashID (csv)', - instructions: $sce.trustAsHtml('Using the SplashID Safe desktop application, click on the SplashID ' + - 'blue lock logo in the top right corner. Navigate to "Export" > "Export as CSV" and save the CSV file.') - }, - { - id: 'passworddragonxml', - name: 'Password Dragon (xml)', - instructions: $sce.trustAsHtml('Using the Password Dragon desktop application, navigate to "File" > ' + - '"Export" > "To XML". In the dialog that pops up select "All Rows" and check all fields. Click ' + - 'the "Export" button and save the XML file.') - }, - { - id: 'padlockcsv', - name: 'Padlock (csv)', - instructions: $sce.trustAsHtml('Using the Padlock desktop application, click the hamburger icon ' + - 'in the top left corner and navigate to "Settings". Click the "Export Data" option. Ensure that ' + - 'the "CSV" option is selected from the dropdown. Highlight and copy the data from the textarea. ' + - 'Open a text editor like Notepad and paste the data. Save the data from the text editor as ' + - 'padlock_export.csv.') - }, - { - id: 'clipperzhtml', - name: 'Clipperz (html)', - instructions: $sce.trustAsHtml('Log into the Clipperz web application (clipperz.is/app). Click the ' + - 'hamburger menu icon in the top right to expand the navigation bar. Navigate to "Data" > ' + - '"Export". Click the "download HTML+JSON" button to save the HTML file.') - }, - { - id: 'avirajson', - name: 'Avira (json)', - instructions: $sce.trustAsHtml('Using the Avira browser extension, click your username in the top ' + - 'right corner and navigate to "Settings". Locate the "Export Data" section and click "Export". ' + - 'In the dialog that pops up, click the "Export Password Manager Data" button to save the ' + - 'TXT/JSON file.') - }, - { - id: 'saferpasscsv', - name: 'SaferPass (csv)', - instructions: $sce.trustAsHtml('Using the SaferPass browser extension, click the hamburger icon ' + - 'in the top left corner and navigate to "Settings". Click the "Export accounts" button to ' + - 'save the CSV file.') - }, - { - id: 'upmcsv', - name: 'Universal Password Manager (csv)', - instructions: $sce.trustAsHtml('Using the Universal Password Manager desktop application, navigate ' + - 'to "Database" > "Export" and save the CSV file.') - }, - { - id: 'ascendocsv', - name: 'Ascendo DataVault (csv)', - instructions: $sce.trustAsHtml('Using the Ascendo DataVault desktop application, navigate ' + - 'to "Tools" > "Export". In the dialog that pops up, select the "All Items (DVX, CSV)" ' + - 'option. Click the "Ok" button to save the CSV file.') - }, - { - id: 'meldiumcsv', - name: 'Meldium (csv)', - instructions: $sce.trustAsHtml('Using the Meldium web vault, navigate to "Settings". ' + - 'Locate the "Export data" function and click "Show me my data" to save the CSV file.') - }, - { - id: 'passkeepcsv', - name: 'PassKeep (csv)', - instructions: $sce.trustAsHtml('Using the PassKeep mobile app, navigate to "Backup/Restore". ' + - 'Locate the "CSV Backup/Restore" section and click "Backup to CSV" to save the CSV file.') - }, - { - id: 'operacsv', - name: 'Opera (csv)', - instructions: $sce.trustAsHtml('The process for importing from Opera is exactly the same as ' + - 'importing from Google Chrome. See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-chrome/') - }, - { - id: 'vivaldicsv', - name: 'Vivaldi (csv)', - instructions: $sce.trustAsHtml('The process for importing from Vivaldi is exactly the same as ' + - 'importing from Google Chrome. See detailed instructions on our help site at ' + - '' + - 'https://help.bitwarden.com/article/import-from-chrome/') - }, - { - id: 'gnomejson', - name: 'GNOME Passwords and Keys/Seahorse (json)', - instructions: $sce.trustAsHtml('Make sure you have python-keyring and python-gnomekeyring installed. ' + - 'Save the GNOME Keyring Import/Export ' + - 'python script by Luke Plant to your desktop as pw_helper.py. Open terminal and run ' + - 'chmod +rx Desktop/pw_helper.py and then ' + - 'python Desktop/pw_helper.py export Desktop/my_passwords.json. Then upload ' + - 'the resulting my_passwords.json file here to Bitwarden.') - } - ]; - - $scope.setSource = function () { - for (var i = 0; i < $scope.options.length; i++) { - if ($scope.options[i].id === $scope.model.source) { - $scope.source = $scope.options[i]; - break; - } - } - }; - $scope.setSource(); - - $scope.import = function (model, form) { - if (!model.source || model.source === '') { - validationService.addError(form, 'source', 'Select the format of the import file.', true); - return; - } - - var file = document.getElementById('file').files[0]; - if (!file && (!model.fileContents || model.fileContents === '')) { - validationService.addError(form, 'file', 'Select the import file or copy/paste the import file contents.', true); - return; - } - - $scope.processing = true; - importService.import(model.source, file || model.fileContents, importSuccess, importError); - }; - - function importSuccess(folders, ciphers, folderRelationships) { - if (!folders.length && !ciphers.length) { - importError('Nothing was imported.'); - return; - } - else if (ciphers.length) { - var halfway = Math.floor(ciphers.length / 2); - var last = ciphers.length - 1; - if (cipherIsBadData(ciphers[0]) && cipherIsBadData(ciphers[halfway]) && cipherIsBadData(ciphers[last])) { - importError('Data is not formatted correctly. Please check your import file and try again.'); - return; - } - } - - apiService.ciphers.import({ - folders: cipherService.encryptFolders(folders), - ciphers: cipherService.encryptCiphers(ciphers), - folderRelationships: folderRelationships - }, function () { - $uibModalInstance.dismiss('cancel'); - $state.go('backend.user.vault', { refreshFromServer: true }).then(function () { - $analytics.eventTrack('Imported Data', { label: $scope.model.source }); - toastr.success('Data has been successfully imported into your vault.', 'Import Success'); - }); - }, importError); - } - - function cipherIsBadData(cipher) { - return (cipher.name === null || cipher.name === '--') && - (cipher.login && (cipher.login.password === null || cipher.login.password === '')); - } - - function importError(error) { - $analytics.eventTrack('Import Data Failed', { label: $scope.model.source }); - $uibModalInstance.dismiss('cancel'); - - if (error) { - var data = error.data; - if (data && data.ValidationErrors) { - var message = ''; - for (var key in data.ValidationErrors) { - if (!data.ValidationErrors.hasOwnProperty(key)) { - continue; - } - - for (var i = 0; i < data.ValidationErrors[key].length; i++) { - message += (key + ': ' + data.ValidationErrors[key][i] + ' '); - } - } - - if (message !== '') { - toastr.error(message); - return; - } - } - else if (data && data.Message) { - toastr.error(data.Message); - return; - } - else { - toastr.error(error); - return; - } - } - - toastr.error('Something went wrong. Try again.', 'Oh No!'); - } - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/tools/toolsModule.js b/src/app/tools/toolsModule.js deleted file mode 100644 index 98191f4998..0000000000 --- a/src/app/tools/toolsModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.tools', ['ui.bootstrap', 'toastr']); diff --git a/src/app/tools/views/tools.html b/src/app/tools/views/tools.html deleted file mode 100644 index 242994eb20..0000000000 --- a/src/app/tools/views/tools.html +++ /dev/null @@ -1,32 +0,0 @@ -
-

- Tools - helpful utilities -

-
-
-
-
-

Import/Export

-
-
-

- Quickly import your logins and other data from a previous export or from another - password management application. -

-

You can also export all of your vault data in .csv format.

-
- -
-
-
-

Password Generator

-
-
- Password generator is currently available in all other client applications. Coming soon to the web vault! -
-
-
diff --git a/src/app/tools/views/toolsExport.html b/src/app/tools/views/toolsExport.html deleted file mode 100644 index 2a2ecf0552..0000000000 --- a/src/app/tools/views/toolsExport.html +++ /dev/null @@ -1,33 +0,0 @@ - -
- - -
- diff --git a/src/app/tools/views/toolsImport.html b/src/app/tools/views/toolsImport.html deleted file mode 100644 index b0d28d74c8..0000000000 --- a/src/app/tools/views/toolsImport.html +++ /dev/null @@ -1,48 +0,0 @@ - -
- - -
- diff --git a/src/app/vault/add-edit.component.html b/src/app/vault/add-edit.component.html new file mode 100644 index 0000000000..3e22420ae8 --- /dev/null +++ b/src/app/vault/add-edit.component.html @@ -0,0 +1,371 @@ + diff --git a/src/app/vault/add-edit.component.ts b/src/app/vault/add-edit.component.ts new file mode 100644 index 0000000000..d4b87c552b --- /dev/null +++ b/src/app/vault/add-edit.component.ts @@ -0,0 +1,133 @@ +import { + Component, + OnInit, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherType } from 'jslib/enums/cipherType'; + +import { AuditService } from 'jslib/abstractions/audit.service'; +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { StateService } from 'jslib/abstractions/state.service'; +import { TokenService } from 'jslib/abstractions/token.service'; +import { TotpService } from 'jslib/abstractions/totp.service'; + +import { AddEditComponent as BaseAddEditComponent } from 'jslib/angular/components/add-edit.component'; +import { LoginUriView } from 'jslib/models/view/loginUriView'; + +@Component({ + selector: 'app-vault-add-edit', + templateUrl: 'add-edit.component.html', +}) +export class AddEditComponent extends BaseAddEditComponent implements OnInit { + isPremium: boolean; + totpCode: string; + totpCodeFormatted: string; + totpDash: number; + totpSec: number; + totpLow: boolean; + + protected totpInterval: number; + + constructor(cipherService: CipherService, folderService: FolderService, + i18nService: I18nService, platformUtilsService: PlatformUtilsService, + analytics: Angulartics2, toasterService: ToasterService, + auditService: AuditService, stateService: StateService, + protected tokenService: TokenService, protected totpService: TotpService, + protected passwordGenerationService: PasswordGenerationService) { + super(cipherService, folderService, i18nService, platformUtilsService, analytics, + toasterService, auditService, stateService); + } + + async ngOnInit() { + await super.load(); + this.cleanUp(); + + this.isPremium = this.tokenService.getPremium(); + if (this.cipher.type === CipherType.Login && this.cipher.login.totp && + (this.cipher.organizationUseTotp || this.isPremium)) { + await this.totpUpdateCode(); + await this.totpTick(); + + this.totpInterval = window.setInterval(async () => { + await this.totpTick(); + }, 1000); + } + } + + toggleFavorite() { + this.cipher.favorite = !this.cipher.favorite; + } + + launch(uri: LoginUriView) { + if (!uri.canLaunch) { + return; + } + + this.analytics.eventTrack.next({ action: 'Launched Login URI' }); + this.platformUtilsService.launchUri(uri.uri); + } + + copy(value: string, typeI18nKey: string, aType: string) { + if (value == null) { + return; + } + + this.analytics.eventTrack.next({ action: 'Copied ' + aType }); + this.platformUtilsService.copyToClipboard(value, { doc: window.document }); + this.toasterService.popAsync('info', null, + this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey))); + } + + async generatePassword(): Promise { + const confirmed = await super.generatePassword(); + if (confirmed) { + const options = await this.passwordGenerationService.getOptions(); + this.cipher.login.password = await this.passwordGenerationService.generatePassword(options); + } + return confirmed; + } + + protected cleanUp() { + if (this.totpInterval) { + window.clearInterval(this.totpInterval); + } + } + + protected async totpUpdateCode() { + if (this.cipher == null || this.cipher.type !== CipherType.Login || this.cipher.login.totp == null) { + if (this.totpInterval) { + window.clearInterval(this.totpInterval); + } + return; + } + + this.totpCode = await this.totpService.getCode(this.cipher.login.totp); + if (this.totpCode != null) { + this.totpCodeFormatted = this.totpCode.substring(0, 3) + ' ' + this.totpCode.substring(3); + } else { + this.totpCodeFormatted = null; + if (this.totpInterval) { + window.clearInterval(this.totpInterval); + } + } + } + + protected async totpTick() { + const epoch = Math.round(new Date().getTime() / 1000.0); + const mod = epoch % 30; + + this.totpSec = 30 - mod; + this.totpDash = +(Math.round(((2.62 * mod) + 'e+2') as any) + 'e-2'); + this.totpLow = this.totpSec <= 7; + if (mod === 0) { + await this.totpUpdateCode(); + } + } +} diff --git a/src/app/vault/attachments.component.html b/src/app/vault/attachments.component.html new file mode 100644 index 0000000000..67bbb1b57f --- /dev/null +++ b/src/app/vault/attachments.component.html @@ -0,0 +1,50 @@ + diff --git a/src/app/vault/attachments.component.ts b/src/app/vault/attachments.component.ts new file mode 100644 index 0000000000..1b086de522 --- /dev/null +++ b/src/app/vault/attachments.component.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CryptoService } from 'jslib/abstractions/crypto.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { TokenService } from 'jslib/abstractions/token.service'; + +import { AttachmentsComponent as BaseAttachmentsComponent } from 'jslib/angular/components/attachments.component'; + +@Component({ + selector: 'app-vault-attachments', + templateUrl: 'attachments.component.html', +}) +export class AttachmentsComponent extends BaseAttachmentsComponent { + constructor(cipherService: CipherService, analytics: Angulartics2, + toasterService: ToasterService, i18nService: I18nService, + cryptoService: CryptoService, tokenService: TokenService, + platformUtilsService: PlatformUtilsService) { + super(cipherService, analytics, toasterService, i18nService, cryptoService, tokenService, + platformUtilsService, window); + } +} diff --git a/src/app/vault/bulk-delete.component.html b/src/app/vault/bulk-delete.component.html new file mode 100644 index 0000000000..de082860c9 --- /dev/null +++ b/src/app/vault/bulk-delete.component.html @@ -0,0 +1,24 @@ + diff --git a/src/app/vault/bulk-delete.component.ts b/src/app/vault/bulk-delete.component.ts new file mode 100644 index 0000000000..ae15150143 --- /dev/null +++ b/src/app/vault/bulk-delete.component.ts @@ -0,0 +1,34 @@ +import { + Component, + EventEmitter, + Input, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +@Component({ + selector: 'app-vault-bulk-delete', + templateUrl: 'bulk-delete.component.html', +}) +export class BulkDeleteComponent { + @Input() cipherIds: string[] = []; + @Output() onDeleted = new EventEmitter(); + + formPromise: Promise; + + constructor(private analytics: Angulartics2, private cipherService: CipherService, + private toasterService: ToasterService, private i18nService: I18nService) { } + + async submit() { + this.formPromise = this.cipherService.deleteManyWithServer(this.cipherIds); + await this.formPromise; + this.onDeleted.emit(); + this.analytics.eventTrack.next({ action: 'Bulk Deleted Items' }); + this.toasterService.popAsync('success', null, this.i18nService.t('deletedItems')); + } +} diff --git a/src/app/vault/bulk-move.component.html b/src/app/vault/bulk-move.component.html new file mode 100644 index 0000000000..7af391b90a --- /dev/null +++ b/src/app/vault/bulk-move.component.html @@ -0,0 +1,30 @@ + diff --git a/src/app/vault/bulk-move.component.ts b/src/app/vault/bulk-move.component.ts new file mode 100644 index 0000000000..c5b6d62885 --- /dev/null +++ b/src/app/vault/bulk-move.component.ts @@ -0,0 +1,46 @@ +import { + Component, + EventEmitter, + Input, + OnInit, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { FolderView } from 'jslib/models/view/folderView'; + +@Component({ + selector: 'app-vault-bulk-move', + templateUrl: 'bulk-move.component.html', +}) +export class BulkMoveComponent implements OnInit { + @Input() cipherIds: string[] = []; + @Output() onMoved = new EventEmitter(); + + folderId: string = null; + folders: FolderView[] = []; + formPromise: Promise; + + constructor(private analytics: Angulartics2, private cipherService: CipherService, + private toasterService: ToasterService, private i18nService: I18nService, + private folderService: FolderService) { } + + async ngOnInit() { + this.folders = await this.folderService.getAllDecrypted(); + this.folderId = this.folders[0].id; + } + + async submit() { + this.formPromise = this.cipherService.moveManyWithServer(this.cipherIds, this.folderId); + await this.formPromise; + this.onMoved.emit(); + this.analytics.eventTrack.next({ action: 'Bulk Moved Items' }); + this.toasterService.popAsync('success', null, this.i18nService.t('movedItems')); + } +} diff --git a/src/app/vault/bulk-share.component.html b/src/app/vault/bulk-share.component.html new file mode 100644 index 0000000000..0441f5b7f1 --- /dev/null +++ b/src/app/vault/bulk-share.component.html @@ -0,0 +1,54 @@ + diff --git a/src/app/vault/bulk-share.component.ts b/src/app/vault/bulk-share.component.ts new file mode 100644 index 0000000000..7bc9e0d36e --- /dev/null +++ b/src/app/vault/bulk-share.component.ts @@ -0,0 +1,86 @@ +import { + Component, + EventEmitter, + Input, + OnInit, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { CipherView } from 'jslib/models/view'; +import { CollectionView } from 'jslib/models/view/collectionView'; + +import { Organization } from 'jslib/models/domain/organization'; + +@Component({ + selector: 'app-vault-bulk-share', + templateUrl: 'bulk-share.component.html', +}) +export class BulkShareComponent implements OnInit { + @Input() ciphers: CipherView[] = []; + @Input() organizationId: string; + @Output() onShared = new EventEmitter(); + + nonShareableCount = 0; + collections: CollectionView[] = []; + organizations: Organization[] = []; + formPromise: Promise; + + private writeableCollections: CollectionView[] = []; + private shareableCiphers: CipherView[] = []; + + constructor(private analytics: Angulartics2, private cipherService: CipherService, + private toasterService: ToasterService, private i18nService: I18nService, + private collectionService: CollectionService, private userService: UserService) { } + + async ngOnInit() { + this.shareableCiphers = this.ciphers.filter((c) => !c.hasAttachments && c.organizationId == null); + this.nonShareableCount = this.ciphers.length - this.shareableCiphers.length; + const allCollections = await this.collectionService.getAllDecrypted(); + this.writeableCollections = allCollections.filter((c) => !c.readOnly); + this.organizations = await this.userService.getAllOrganizations(); + if (this.organizationId == null && this.organizations.length > 0) { + this.organizationId = this.organizations[0].id; + } + this.filterCollections(); + } + + ngOnDestroy() { + this.selectAll(false); + } + + filterCollections() { + this.selectAll(false); + if (this.organizationId == null || this.writeableCollections.length === 0) { + this.collections = []; + } else { + this.collections = this.writeableCollections.filter((c) => c.organizationId === this.organizationId); + } + } + + async submit() { + const checkedCollectionIds = this.collections.filter((c) => (c as any).checked).map((c) => c.id); + this.formPromise = this.cipherService.shareManyWithServer(this.shareableCiphers, this.organizationId, + checkedCollectionIds); + await this.formPromise; + this.onShared.emit(); + this.analytics.eventTrack.next({ action: 'Bulk Shared Items' }); + this.toasterService.popAsync('success', null, this.i18nService.t('sharedItems')); + } + + check(c: CollectionView, select?: boolean) { + (c as any).checked = select == null ? !(c as any).checked : select; + } + + selectAll(select: boolean) { + const collections = select ? this.collections : this.writeableCollections; + collections.forEach((c) => this.check(c, select)); + } +} diff --git a/src/app/vault/ciphers.component.html b/src/app/vault/ciphers.component.html new file mode 100644 index 0000000000..d8566ed3ea --- /dev/null +++ b/src/app/vault/ciphers.component.html @@ -0,0 +1,59 @@ + + + + + + + + + + +
+ + + + + {{c.name}} + + +
+ {{c.subTitle}} +
+ +
+
+ + +

{{'noItemsInList' | i18n}}

+ +
+
+
diff --git a/src/app/vault/ciphers.component.ts b/src/app/vault/ciphers.component.ts new file mode 100644 index 0000000000..50afe5e496 --- /dev/null +++ b/src/app/vault/ciphers.component.ts @@ -0,0 +1,102 @@ +import { + Component, + EventEmitter, + Input, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { CiphersComponent as BaseCiphersComponent } from 'jslib/angular/components/ciphers.component'; + +import { CipherType } from 'jslib/enums/cipherType'; + +import { CipherView } from 'jslib/models/view/cipherView'; + +const MaxCheckedCount = 500; + +@Component({ + selector: 'app-vault-ciphers', + templateUrl: 'ciphers.component.html', +}) +export class CiphersComponent extends BaseCiphersComponent { + @Input() showAddNew = true; + @Output() onAttachmentsClicked = new EventEmitter(); + @Output() onShareClicked = new EventEmitter(); + @Output() onCollectionsClicked = new EventEmitter(); + + cipherType = CipherType; + + constructor(cipherService: CipherService, protected analytics: Angulartics2, + protected toasterService: ToasterService, protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService) { + super(cipherService); + } + + checkCipher(c: CipherView, select?: boolean) { + (c as any).checked = select == null ? !(c as any).checked : select; + } + + selectAll(select: boolean) { + if (select) { + this.selectAll(false); + } + const selectCount = select && this.ciphers.length > MaxCheckedCount ? MaxCheckedCount : this.ciphers.length; + for (let i = 0; i < selectCount; i++) { + this.checkCipher(this.ciphers[i], select); + } + } + + getSelected(): CipherView[] { + if (this.ciphers == null) { + return []; + } + return this.ciphers.filter((c) => !!(c as any).checked); + } + + getSelectedIds(): string[] { + return this.getSelected().map((c) => c.id); + } + + attachments(c: CipherView) { + this.onAttachmentsClicked.emit(c); + } + + share(c: CipherView) { + this.onShareClicked.emit(c); + } + + collections(c: CipherView) { + this.onCollectionsClicked.emit(c); + } + + async delete(c: CipherView): Promise { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t('deleteItemConfirmation'), this.i18nService.t('deleteItem'), + this.i18nService.t('yes'), this.i18nService.t('no'), 'warning'); + if (!confirmed) { + return false; + } + + await this.cipherService.deleteWithServer(c.id); + this.analytics.eventTrack.next({ action: 'Deleted Cipher' }); + this.toasterService.popAsync('success', null, this.i18nService.t('deletedItem')); + this.refresh(); + } + + copy(value: string, typeI18nKey: string, aType: string) { + if (value == null) { + return; + } + + this.analytics.eventTrack.next({ action: 'Copied ' + aType.toLowerCase() + ' from listing.' }); + this.platformUtilsService.copyToClipboard(value, { doc: window.document }); + this.toasterService.popAsync('info', null, + this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey))); + } +} diff --git a/src/app/vault/collections.component.html b/src/app/vault/collections.component.html new file mode 100644 index 0000000000..e4862316f5 --- /dev/null +++ b/src/app/vault/collections.component.html @@ -0,0 +1,48 @@ + diff --git a/src/app/vault/collections.component.ts b/src/app/vault/collections.component.ts new file mode 100644 index 0000000000..fea8e6d98b --- /dev/null +++ b/src/app/vault/collections.component.ts @@ -0,0 +1,94 @@ +import { + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; + +import { CipherView } from 'jslib/models/view/cipherView'; +import { CollectionView } from 'jslib/models/view/collectionView'; + +import { Cipher } from 'jslib/models/domain/cipher'; + +@Component({ + selector: 'app-vault-collections', + templateUrl: 'collections.component.html', +}) +export class CollectionsComponent implements OnInit, OnDestroy { + @Input() cipherId: string; + @Output() onSavedCollections = new EventEmitter(); + + formPromise: Promise; + cipher: CipherView; + collectionIds: string[]; + collections: CollectionView[] = []; + + protected cipherDomain: Cipher; + + constructor(protected collectionService: CollectionService, protected analytics: Angulartics2, + protected toasterService: ToasterService, protected i18nService: I18nService, + protected cipherService: CipherService) { } + + async ngOnInit() { + this.cipherDomain = await this.loadCipher(); + this.collectionIds = this.loadCipherCollections(); + this.cipher = await this.cipherDomain.decrypt(); + this.collections = await this.loadCollections(); + + this.selectAll(false); + if (this.collectionIds != null) { + this.collections.forEach((c) => { + (c as any).checked = this.collectionIds.indexOf(c.id) > -1; + }); + } + } + + ngOnDestroy() { + this.selectAll(false); + } + + async submit() { + this.cipherDomain.collectionIds = this.collections + .filter((c) => !!(c as any).checked) + .map((c) => c.id); + this.formPromise = this.saveCollections(); + await this.formPromise; + this.onSavedCollections.emit(); + this.analytics.eventTrack.next({ action: 'Edited Cipher Collections' }); + this.toasterService.popAsync('success', null, this.i18nService.t('editedItem')); + } + + check(c: CollectionView, select?: boolean) { + (c as any).checked = select == null ? !(c as any).checked : select; + } + + selectAll(select: boolean) { + this.collections.forEach((c) => this.check(c, select)); + } + + protected loadCipher() { + return this.cipherService.get(this.cipherId); + } + + protected loadCipherCollections() { + return this.cipherDomain.collectionIds; + } + + protected async loadCollections() { + const allCollections = await this.collectionService.getAllDecrypted(); + return allCollections.filter((c) => !c.readOnly && c.organizationId === this.cipher.organizationId); + } + + protected saveCollections() { + return this.cipherService.saveCollectionsWithServer(this.cipherDomain); + } +} diff --git a/src/app/vault/folder-add-edit.component.html b/src/app/vault/folder-add-edit.component.html new file mode 100644 index 0000000000..1159897e4f --- /dev/null +++ b/src/app/vault/folder-add-edit.component.html @@ -0,0 +1,30 @@ + diff --git a/src/app/vault/folder-add-edit.component.ts b/src/app/vault/folder-add-edit.component.ts new file mode 100644 index 0000000000..685a8d09c5 --- /dev/null +++ b/src/app/vault/folder-add-edit.component.ts @@ -0,0 +1,24 @@ +import { Component } from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { FolderService } from 'jslib/abstractions/folder.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { + FolderAddEditComponent as BaseFolderAddEditComponent, +} from 'jslib/angular/components/folder-add-edit.component'; + +@Component({ + selector: 'app-folder-add-edit', + templateUrl: 'folder-add-edit.component.html', +}) +export class FolderAddEditComponent extends BaseFolderAddEditComponent { + constructor(folderService: FolderService, i18nService: I18nService, + analytics: Angulartics2, toasterService: ToasterService, + platformUtilsService: PlatformUtilsService) { + super(folderService, i18nService, analytics, toasterService, platformUtilsService); + } +} diff --git a/src/app/vault/groupings.component.html b/src/app/vault/groupings.component.html new file mode 100644 index 0000000000..fc9fee31fe --- /dev/null +++ b/src/app/vault/groupings.component.html @@ -0,0 +1,76 @@ +
+
+ Filters +
+
+ + +

{{'types' | i18n}}

+ +

+ +

+ + +

+ {{'folders' | i18n}} + + + +

+ +
+ +

{{'collections' | i18n}}

+ +
+
+
+
diff --git a/src/app/vault/groupings.component.ts b/src/app/vault/groupings.component.ts new file mode 100644 index 0000000000..5d1611bb06 --- /dev/null +++ b/src/app/vault/groupings.component.ts @@ -0,0 +1,29 @@ +import { + Component, + EventEmitter, + Output, +} from '@angular/core'; + +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { FolderService } from 'jslib/abstractions/folder.service'; + +import { GroupingsComponent as BaseGroupingsComponent } from 'jslib/angular/components/groupings.component'; + +@Component({ + selector: 'app-vault-groupings', + templateUrl: 'groupings.component.html', +}) +export class GroupingsComponent extends BaseGroupingsComponent { + @Output() onSearchTextChanged = new EventEmitter(); + + searchText: string = ''; + searchPlaceholder: string = null; + + constructor(collectionService: CollectionService, folderService: FolderService) { + super(collectionService, folderService); + } + + searchTextChanged() { + this.onSearchTextChanged.emit(this.searchText); + } +} diff --git a/src/app/vault/share.component.html b/src/app/vault/share.component.html new file mode 100644 index 0000000000..fe4b5ca96f --- /dev/null +++ b/src/app/vault/share.component.html @@ -0,0 +1,54 @@ + diff --git a/src/app/vault/share.component.ts b/src/app/vault/share.component.ts new file mode 100644 index 0000000000..586fc044ed --- /dev/null +++ b/src/app/vault/share.component.ts @@ -0,0 +1,98 @@ +import { + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, +} from '@angular/core'; + +import { ToasterService } from 'angular2-toaster'; +import { Angulartics2 } from 'angulartics2'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { Organization } from 'jslib/models/domain/organization'; +import { CipherView } from 'jslib/models/view/cipherView'; +import { CollectionView } from 'jslib/models/view/collectionView'; + +@Component({ + selector: 'app-vault-share', + templateUrl: 'share.component.html', +}) +export class ShareComponent implements OnInit, OnDestroy { + @Input() cipherId: string; + @Input() organizationId: string; + @Output() onSharedCipher = new EventEmitter(); + + formPromise: Promise; + cipher: CipherView; + collections: CollectionView[] = []; + organizations: Organization[] = []; + + private writeableCollections: CollectionView[] = []; + + constructor(private collectionService: CollectionService, private analytics: Angulartics2, + private toasterService: ToasterService, private i18nService: I18nService, + private userService: UserService, private cipherService: CipherService) { } + + async ngOnInit() { + const cipherDomain = await this.cipherService.get(this.cipherId); + this.cipher = await cipherDomain.decrypt(); + const allCollections = await this.collectionService.getAllDecrypted(); + this.writeableCollections = allCollections.filter((c) => !c.readOnly); + this.organizations = await this.userService.getAllOrganizations(); + if (this.organizationId == null && this.organizations.length > 0) { + this.organizationId = this.organizations[0].id; + } + this.filterCollections(); + } + + ngOnDestroy() { + this.selectAll(false); + } + + filterCollections() { + this.selectAll(false); + if (this.organizationId == null || this.writeableCollections.length === 0) { + this.collections = []; + } else { + this.collections = this.writeableCollections.filter((c) => c.organizationId === this.organizationId); + } + } + + async submit() { + const cipherDomain = await this.cipherService.get(this.cipherId); + const cipherView = await cipherDomain.decrypt(); + + const attachmentPromises: Array> = []; + if (cipherView.attachments != null) { + for (const attachment of cipherView.attachments) { + const promise = this.cipherService.shareAttachmentWithServer(attachment, + cipherView.id, this.organizationId); + attachmentPromises.push(promise); + } + } + + const checkedCollectionIds = this.collections.filter((c) => (c as any).checked).map((c) => c.id); + this.formPromise = Promise.all(attachmentPromises).then(async () => { + await this.cipherService.shareWithServer(cipherView, this.organizationId, checkedCollectionIds); + this.onSharedCipher.emit(); + this.analytics.eventTrack.next({ action: 'Shared Cipher' }); + this.toasterService.popAsync('success', null, this.i18nService.t('sharedItem')); + }); + await this.formPromise; + } + + check(c: CollectionView, select?: boolean) { + (c as any).checked = select == null ? !(c as any).checked : select; + } + + selectAll(select: false) { + const collections = select ? this.collections : this.writeableCollections; + collections.forEach((c) => this.check(c, select)); + } +} diff --git a/src/app/vault/vault.component.html b/src/app/vault/vault.component.html new file mode 100644 index 0000000000..492092f7ce --- /dev/null +++ b/src/app/vault/vault.component.html @@ -0,0 +1,75 @@ +
+
+
+ + +
+ +
+
+
+ Some callout +
+
+
+
+ {{'organizations' | i18n}} +
+
+ +
+
+
+
+
+ + + + + + + + diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts new file mode 100644 index 0000000000..f631aa0272 --- /dev/null +++ b/src/app/vault/vault.component.ts @@ -0,0 +1,370 @@ +import { Location } from '@angular/common'; +import { + Component, + ComponentFactoryResolver, + OnInit, + ViewChild, + ViewContainerRef, +} from '@angular/core'; +import { + ActivatedRoute, + Router, +} from '@angular/router'; + +import { CipherType } from 'jslib/enums/cipherType'; + +import { CipherView } from 'jslib/models/view/cipherView'; + +import { ModalComponent } from '../modal.component'; + +import { AddEditComponent } from './add-edit.component'; +import { AttachmentsComponent } from './attachments.component'; +import { BulkDeleteComponent } from './bulk-delete.component'; +import { CiphersComponent } from './ciphers.component'; +import { CollectionsComponent } from './collections.component'; +import { FolderAddEditComponent } from './folder-add-edit.component'; +import { GroupingsComponent } from './groupings.component'; +import { ShareComponent } from './share.component'; + +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { SyncService } from 'jslib/abstractions/sync.service'; +import { BulkMoveComponent } from './bulk-move.component'; +import { BulkShareComponent } from './bulk-share.component'; + +@Component({ + selector: 'app-vault', + templateUrl: 'vault.component.html', +}) +export class VaultComponent implements OnInit { + @ViewChild(GroupingsComponent) groupingsComponent: GroupingsComponent; + @ViewChild(CiphersComponent) ciphersComponent: CiphersComponent; + @ViewChild('attachments', { read: ViewContainerRef }) attachmentsModalRef: ViewContainerRef; + @ViewChild('folderAddEdit', { read: ViewContainerRef }) folderAddEditModalRef: ViewContainerRef; + @ViewChild('cipherAddEdit', { read: ViewContainerRef }) cipherAddEditModalRef: ViewContainerRef; + @ViewChild('share', { read: ViewContainerRef }) shareModalRef: ViewContainerRef; + @ViewChild('collections', { read: ViewContainerRef }) collectionsModalRef: ViewContainerRef; + @ViewChild('bulkDeleteTemplate', { read: ViewContainerRef }) bulkDeleteModalRef: ViewContainerRef; + @ViewChild('bulkMoveTemplate', { read: ViewContainerRef }) bulkMoveModalRef: ViewContainerRef; + @ViewChild('bulkShareTemplate', { read: ViewContainerRef }) bulkShareModalRef: ViewContainerRef; + + favorites: boolean = false; + type: CipherType = null; + folderId: string = null; + collectionId: string = null; + + private modal: ModalComponent = null; + + constructor(private syncService: SyncService, private route: ActivatedRoute, + private router: Router, private location: Location, + private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver) { } + + async ngOnInit() { + this.route.queryParams.subscribe(async (params) => { + await this.syncService.fullSync(false); + await this.groupingsComponent.load(); + + if (params == null) { + this.groupingsComponent.selectedAll = true; + await this.ciphersComponent.load(); + return; + } + + if (params.favorites) { + this.groupingsComponent.selectedFavorites = true; + await this.filterFavorites(); + } else if (params.type) { + const t = parseInt(params.type, null); + this.groupingsComponent.selectedType = t; + await this.filterCipherType(t); + } else if (params.folderId) { + this.groupingsComponent.selectedFolder = true; + this.groupingsComponent.selectedFolderId = params.folderId; + await this.filterFolder(params.folderId); + } else if (params.collectionId) { + this.groupingsComponent.selectedCollectionId = params.collectionId; + await this.filterCollection(params.collectionId); + } else { + this.groupingsComponent.selectedAll = true; + await this.ciphersComponent.load(); + } + }); + } + + async clearGroupingFilters() { + this.ciphersComponent.showAddNew = true; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchVault'); + await this.ciphersComponent.load(); + this.clearFilters(); + this.go(); + } + + async filterFavorites() { + this.ciphersComponent.showAddNew = true; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchFavorites'); + await this.ciphersComponent.load((c) => c.favorite); + this.clearFilters(); + this.favorites = true; + this.go(); + } + + async filterCipherType(type: CipherType) { + this.ciphersComponent.showAddNew = true; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchType'); + await this.ciphersComponent.load((c) => c.type === type); + this.clearFilters(); + this.type = type; + this.go(); + } + + async filterFolder(folderId: string) { + this.ciphersComponent.showAddNew = true; + folderId = folderId === 'none' ? null : folderId; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchFolder'); + await this.ciphersComponent.load((c) => c.folderId === folderId); + this.clearFilters(); + this.folderId = folderId == null ? 'none' : folderId; + this.go(); + } + + async filterCollection(collectionId: string) { + this.ciphersComponent.showAddNew = false; + this.groupingsComponent.searchPlaceholder = this.i18nService.t('searchCollection'); + await this.ciphersComponent.load((c) => c.collectionIds.indexOf(collectionId) > -1); + this.clearFilters(); + this.collectionId = collectionId; + this.go(); + } + + filterSearchText(searchText: string) { + this.ciphersComponent.searchText = searchText; + } + + editCipherAttachments(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.attachmentsModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(AttachmentsComponent, this.attachmentsModalRef); + + childComponent.cipherId = cipher.id; + let madeAttachmentChanges = false; + childComponent.onUploadedAttachment.subscribe(() => madeAttachmentChanges = true); + childComponent.onDeletedAttachment.subscribe(() => madeAttachmentChanges = true); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + if (madeAttachmentChanges) { + await this.ciphersComponent.refresh(); + } + madeAttachmentChanges = false; + }); + } + + shareCipher(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.shareModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(ShareComponent, this.shareModalRef); + + childComponent.cipherId = cipher.id; + childComponent.onSharedCipher.subscribe(async () => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + editCipherCollections(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.collectionsModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(CollectionsComponent, this.collectionsModalRef); + + childComponent.cipherId = cipher.id; + childComponent.onSavedCollections.subscribe(async () => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + async addFolder() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.folderAddEditModalRef.createComponent(factory).instance; + const childComponent = this.modal.show( + FolderAddEditComponent, this.folderAddEditModalRef); + + childComponent.folderId = null; + childComponent.onSavedFolder.subscribe(async () => { + this.modal.close(); + await this.groupingsComponent.loadFolders(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + async editFolder(folderId: string) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.folderAddEditModalRef.createComponent(factory).instance; + const childComponent = this.modal.show( + FolderAddEditComponent, this.folderAddEditModalRef); + + childComponent.folderId = folderId; + childComponent.onSavedFolder.subscribe(async () => { + this.modal.close(); + await this.groupingsComponent.loadFolders(); + }); + childComponent.onDeletedFolder.subscribe(async () => { + this.modal.close(); + await this.groupingsComponent.loadFolders(); + await this.filterFolder('none'); + this.groupingsComponent.selectedFolderId = null; + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + addCipher() { + const component = this.editCipher(null); + component.type = this.type; + component.folderId = this.folderId === 'none' ? null : this.folderId; + } + + editCipher(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.cipherAddEditModalRef.createComponent(factory).instance; + const childComponent = this.modal.show( + AddEditComponent, this.cipherAddEditModalRef); + + childComponent.cipherId = cipher == null ? null : cipher.id; + childComponent.onSavedCipher.subscribe(async (c: CipherView) => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + childComponent.onDeletedCipher.subscribe(async (c: CipherView) => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + + return childComponent; + } + + bulkDelete() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.bulkDeleteModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(BulkDeleteComponent, this.bulkDeleteModalRef); + + childComponent.cipherIds = this.ciphersComponent.getSelectedIds(); + childComponent.onDeleted.subscribe(async () => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + bulkShare() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.bulkShareModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(BulkShareComponent, this.bulkShareModalRef); + + childComponent.ciphers = this.ciphersComponent.getSelected(); + childComponent.onShared.subscribe(async () => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + bulkMove() { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.bulkMoveModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(BulkMoveComponent, this.bulkMoveModalRef); + + childComponent.cipherIds = this.ciphersComponent.getSelectedIds(); + childComponent.onMoved.subscribe(async () => { + this.modal.close(); + await this.ciphersComponent.refresh(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + selectAll(select: boolean) { + this.ciphersComponent.selectAll(select); + } + + private clearFilters() { + this.folderId = null; + this.collectionId = null; + this.favorites = false; + this.type = null; + } + + private go(queryParams: any = null) { + if (queryParams == null) { + queryParams = { + favorites: this.favorites ? true : null, + type: this.type, + folderId: this.folderId, + collectionId: this.collectionId, + }; + } + + const url = this.router.createUrlTree(['vault'], { queryParams: queryParams }).toString(); + this.location.go(url); + } +} diff --git a/src/app/vault/vaultAddCipherController.js b/src/app/vault/vaultAddCipherController.js deleted file mode 100644 index d35bf5b064..0000000000 --- a/src/app/vault/vaultAddCipherController.js +++ /dev/null @@ -1,156 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultAddCipherController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, - passwordService, selectedFolder, $analytics, checkedFavorite, $rootScope, authService, $uibModal, constants, - $filter, selectedType) { - $analytics.eventTrack('vaultAddCipherController', { category: 'Modal' }); - $scope.folders = $rootScope.vaultFolders; - $scope.constants = constants; - $scope.selectedType = selectedType ? selectedType.toString() : constants.cipherType.login.toString(); - $scope.cipher = { - folderId: selectedFolder ? selectedFolder.id : null, - favorite: checkedFavorite === true, - type: selectedType || constants.cipherType.login, - login: { - uris: [{ - uri: null, - match: null, - matchValue: null - }] - }, - identity: {}, - card: {}, - secureNote: { - type: 0 - } - }; - - authService.getUserProfile().then(function (profile) { - $scope.useTotp = profile.premium; - }); - - $scope.typeChanged = function () { - $scope.cipher.type = parseInt($scope.selectedType); - }; - - $scope.savePromise = null; - $scope.save = function () { - if ($scope.cipher.type === constants.cipherType.login && $scope.cipher.login.uris.length === 1 && - ($scope.cipher.login.uris[0].uri == null || $scope.cipher.login.uris[0].uri === '')) { - $scope.cipher.login.uris = null; - } - - var cipher = cipherService.encryptCipher($scope.cipher); - $scope.savePromise = apiService.ciphers.post(cipher, function (cipherResponse) { - $analytics.eventTrack('Created Cipher'); - var decCipher = cipherService.decryptCipherPreview(cipherResponse); - $uibModalInstance.close(decCipher); - }).$promise; - }; - - $scope.generatePassword = function () { - if (!$scope.cipher.login.password || confirm('Are you sure you want to overwrite the current password?')) { - $analytics.eventTrack('Generated Password From Add'); - $scope.cipher.login.password = passwordService.generatePassword({ length: 14, special: true }); - } - }; - - $scope.addUri = function () { - if (!$scope.cipher.login) { - return; - } - - if (!$scope.cipher.login.uris) { - $scope.cipher.login.uris = []; - } - - $scope.cipher.login.uris.push({ - uri: null, - match: null, - matchValue: null - }); - }; - - $scope.removeUri = function (uri) { - if (!$scope.cipher.login || !$scope.cipher.login.uris) { - return; - } - - var index = $scope.cipher.login.uris.indexOf(uri); - if (index > -1) { - $scope.cipher.login.uris.splice(index, 1); - } - }; - - $scope.uriMatchChanged = function (uri) { - if ((!uri.matchValue && uri.matchValue !== 0) || uri.matchValue === '') { - uri.match = null; - } - else { - uri.match = parseInt(uri.matchValue); - } - }; - - $scope.addField = function () { - if (!$scope.cipher.fields) { - $scope.cipher.fields = []; - } - - $scope.cipher.fields.push({ - type: constants.fieldType.text.toString(), - name: null, - value: null - }); - }; - - $scope.removeField = function (field) { - var index = $scope.cipher.fields.indexOf(field); - if (index > -1) { - $scope.cipher.fields.splice(index, 1); - } - }; - - $scope.toggleFavorite = function () { - $scope.cipher.favorite = !$scope.cipher.favorite; - }; - - $scope.clipboardSuccess = function (e) { - e.clearSelection(); - selectPassword(e); - }; - - $scope.clipboardError = function (e, password) { - if (password) { - selectPassword(e); - } - alert('Your web browser does not support easy clipboard copying. Copy it manually instead.'); - }; - - $scope.folderSort = function (item) { - if (!item.id) { - return ''; - } - - return item.name.toLowerCase(); - }; - - function selectPassword(e) { - var target = $(e.trigger).parent().prev(); - if (target.attr('type') === 'text') { - target.select(); - } - } - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - - $scope.showUpgrade = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/premiumRequired.html', - controller: 'premiumRequiredController' - }); - }; - }); diff --git a/src/app/vault/vaultAddFolderController.js b/src/app/vault/vaultAddFolderController.js deleted file mode 100644 index 536407a491..0000000000 --- a/src/app/vault/vaultAddFolderController.js +++ /dev/null @@ -1,19 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultAddFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, $analytics) { - $analytics.eventTrack('vaultAddFolderController', { category: 'Modal' }); - $scope.savePromise = null; - $scope.save = function (model) { - var folder = cipherService.encryptFolder(model); - $scope.savePromise = apiService.folders.post(folder, function (response) { - $analytics.eventTrack('Created Folder'); - var decFolder = cipherService.decryptFolder(response); - $uibModalInstance.close(decFolder); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('close'); - }; - }); diff --git a/src/app/vault/vaultAttachmentsController.js b/src/app/vault/vaultAttachmentsController.js deleted file mode 100644 index 7556ad3750..0000000000 --- a/src/app/vault/vaultAttachmentsController.js +++ /dev/null @@ -1,122 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultAttachmentsController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, - cipherId, $analytics, validationService, toastr, $timeout, authService, $uibModal) { - $analytics.eventTrack('vaultAttachmentsController', { category: 'Modal' }); - $scope.cipher = {}; - $scope.readOnly = true; - $scope.loading = true; - $scope.isPremium = true; - $scope.canUseAttachments = true; - var closing = false; - - authService.getUserProfile().then(function (profile) { - $scope.isPremium = profile.premium; - return apiService.ciphers.get({ id: cipherId }).$promise; - }).then(function (cipher) { - $scope.cipher = cipherService.decryptCipher(cipher); - $scope.readOnly = !$scope.cipher.edit; - $scope.canUseAttachments = $scope.isPremium || $scope.cipher.organizationId; - $scope.loading = false; - }, function () { - $scope.loading = false; - }); - - $scope.save = function (form) { - var fileEl = document.getElementById('file'); - var files = fileEl.files; - if (!files || !files.length) { - validationService.addError(form, 'file', 'Select a file.', true); - return; - } - - $scope.savePromise = cipherService.encryptAttachmentFile(getKeyForCipher(), files[0]).then(function (encValue) { - var fd = new FormData(); - var blob = new Blob([encValue.data], { type: 'application/octet-stream' }); - fd.append('data', blob, encValue.fileName); - return apiService.ciphers.postAttachment({ id: cipherId }, fd).$promise; - }).then(function (response) { - $analytics.eventTrack('Added Attachment'); - $scope.cipher = cipherService.decryptCipher(response); - - // reset file input - // ref: https://stackoverflow.com/a/20552042 - fileEl.type = ''; - fileEl.type = 'file'; - fileEl.value = ''; - }, function (e) { - var errors = validationService.parseErrors(e); - toastr.error(errors.length ? errors[0] : 'An error occurred.'); - }); - }; - - $scope.download = function (attachment) { - attachment.loading = true; - - if (!$scope.canUseAttachments) { - attachment.loading = false; - alert('Premium membership is required to use this feature.'); - return; - } - - cipherService.downloadAndDecryptAttachment(getKeyForCipher(), attachment, true).then(function (res) { - $timeout(function () { - attachment.loading = false; - }); - }, function () { - $timeout(function () { - attachment.loading = false; - }); - }); - }; - - function getKeyForCipher() { - if ($scope.cipher.organizationId) { - return cryptoService.getOrgKey($scope.cipher.organizationId); - } - - return null; - } - - $scope.remove = function (attachment) { - if (!confirm('Are you sure you want to delete this attachment (' + attachment.fileName + ')?')) { - return; - } - - attachment.loading = true; - apiService.ciphers.delAttachment({ id: cipherId, attachmentId: attachment.id }).$promise.then(function () { - attachment.loading = false; - $analytics.eventTrack('Deleted Attachment'); - var index = $scope.cipher.attachments.indexOf(attachment); - if (index > -1) { - $scope.cipher.attachments.splice(index, 1); - } - }, function () { - toastr.error('Cannot delete attachment.'); - attachment.loading = false; - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - $scope.$on('modal.closing', function (e, reason, closed) { - if (closing) { - return; - } - - e.preventDefault(); - closing = true; - $uibModalInstance.close(!!$scope.cipher.attachments && $scope.cipher.attachments.length > 0); - }); - - $scope.showUpgrade = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/premiumRequired.html', - controller: 'premiumRequiredController' - }); - }; - }); diff --git a/src/app/vault/vaultCipherCollectionsController.js b/src/app/vault/vaultCipherCollectionsController.js deleted file mode 100644 index 9af1d0d77a..0000000000 --- a/src/app/vault/vaultCipherCollectionsController.js +++ /dev/null @@ -1,128 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultCipherCollectionsController', function ($scope, apiService, $uibModalInstance, cipherService, - cipherId, $analytics) { - $analytics.eventTrack('vaultCipherCollectionsController', { category: 'Modal' }); - $scope.cipher = {}; - $scope.readOnly = false; - $scope.loadingCipher = true; - $scope.loadingCollections = true; - $scope.selectedCollections = {}; - $scope.collections = []; - - var cipherAndCols = null; - $uibModalInstance.opened.then(function () { - apiService.ciphers.getDetails({ id: cipherId }).$promise.then(function (cipher) { - $scope.loadingCipher = false; - - $scope.readOnly = !cipher.Edit; - if (cipher.Edit && cipher.OrganizationId) { - if (cipher.Type === 1) { - $scope.cipher = cipherService.decryptCipherPreview(cipher); - } - - var collections = {}; - if (cipher.CollectionIds) { - for (var i = 0; i < cipher.CollectionIds.length; i++) { - collections[cipher.CollectionIds[i]] = null; - } - } - - return { - cipher: cipher, - cipherCollections: collections - }; - } - - return null; - }).then(function (result) { - if (!result) { - $scope.loadingCollections = false; - return false; - } - - cipherAndCols = result; - return apiService.collections.listMe({ writeOnly: true }).$promise; - }).then(function (response) { - if (response === false) { - return; - } - - var collections = []; - var selectedCollections = {}; - var writeableCollections = response.Data; - - for (var i = 0; i < writeableCollections.length; i++) { - // clean out selectCollections that aren't from this organization - if (writeableCollections[i].OrganizationId !== cipherAndCols.cipher.OrganizationId) { - continue; - } - - if (writeableCollections[i].Id in cipherAndCols.cipherCollections) { - selectedCollections[writeableCollections[i].Id] = true; - } - - var decCollection = cipherService.decryptCollection(writeableCollections[i]); - collections.push(decCollection); - } - - $scope.loadingCollections = false; - $scope.collections = collections; - $scope.selectedCollections = selectedCollections; - }); - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - collections[$scope.collections[i].id] = true; - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = true; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - return Object.keys($scope.selectedCollections).length === $scope.collections.length; - }; - - $scope.submit = function () { - var request = { - collectionIds: [] - }; - - for (var id in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(id)) { - request.collectionIds.push(id); - } - } - - $scope.submitPromise = apiService.ciphers.putCollections({ id: cipherId }, request) - .$promise.then(function (response) { - $analytics.eventTrack('Edited Cipher Collections'); - $uibModalInstance.close({ - action: 'collectionsEdit', - collectionIds: request.collectionIds - }); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/vault/vaultController.js b/src/app/vault/vaultController.js deleted file mode 100644 index f4bf780f2a..0000000000 --- a/src/app/vault/vaultController.js +++ /dev/null @@ -1,535 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultController', function ($scope, $uibModal, apiService, $filter, cryptoService, authService, toastr, - cipherService, $q, $localStorage, $timeout, $rootScope, $state, $analytics, constants, validationService) { - $scope.loadingCiphers = true; - $scope.loadingGroupings = true; - $scope.ciphers = []; - $scope.folders = []; - $scope.collections = []; - $scope.constants = constants; - $scope.filter = undefined; - $scope.selectedType = undefined; - $scope.selectedFolder = undefined; - $scope.selectedCollection = undefined; - $scope.selectedFavorites = false; - $scope.selectedAll = true; - $scope.selectedTitle = 'All'; - $scope.selectedIcon = 'fa-th'; - - if ($state.params.refreshFromServer) { - $rootScope.vaultFolders = $rootScope.vaultCollections = $rootScope.vaultCiphers = null; - } - - $scope.$on('$viewContentLoaded', function () { - $timeout(function () { - if ($('body').hasClass('control-sidebar-open')) { - $("#search").focus(); - } - }, 500); - - if (($rootScope.vaultFolders || $rootScope.vaultCollections) && $rootScope.vaultCiphers) { - $scope.loadingCiphers = $scope.loadingGroupings = false; - loadCipherData($rootScope.vaultCiphers); - return; - } - - loadDataFromServer(); - }); - - function loadDataFromServer() { - var decFolders = [{ - id: null, - name: 'No Folder' - }]; - - var decCollections = []; - - var collectionPromise = apiService.collections.listMe({ writeOnly: false }, function (collections) { - for (var i = 0; i < collections.Data.length; i++) { - var decCollection = cipherService.decryptCollection(collections.Data[i], null, true); - decCollections.push(decCollection); - } - }).$promise; - - var folderPromise = apiService.folders.list({}, function (folders) { - for (var i = 0; i < folders.Data.length; i++) { - var decFolder = cipherService.decryptFolderPreview(folders.Data[i]); - decFolders.push(decFolder); - } - }).$promise; - - var groupingPromise = $q.all([collectionPromise, folderPromise]).then(function () { - $rootScope.vaultCollections = decCollections; - $rootScope.vaultFolders = decFolders; - $scope.loadingGroupings = false; - }); - - apiService.ciphers.list({}, function (ciphers) { - var decCiphers = []; - - for (var i = 0; i < ciphers.Data.length; i++) { - var decCipher = cipherService.decryptCipherPreview(ciphers.Data[i]); - decCiphers.push(decCipher); - } - - groupingPromise.then(function () { - loadCipherData(decCiphers); - }); - }); - } - - function loadCipherData(decCiphers) { - $rootScope.vaultCiphers = $scope.ciphers = $filter('orderBy')(decCiphers, ['sort', 'name', 'subTitle']); - - var chunks = chunk($rootScope.vaultCiphers, 200); - if (chunks.length > 0) { - $scope.ciphers = chunks[0]; - var delay = 200; - angular.forEach(chunks, function (value, index) { - delay += 200; - - // skip the first chuck - if (index > 0) { - $timeout(function () { - Array.prototype.push.apply($scope.ciphers, value); - }, delay); - } - }); - } - - $scope.loadingCiphers = false; - } - - function sortScopedCipherData() { - $rootScope.vaultCiphers = $scope.ciphers = $filter('orderBy')($rootScope.vaultCiphers, ['name', 'subTitle']); - } - - function chunk(arr, len) { - var chunks = [], - i = 0, - n = arr.length; - while (i < n) { - chunks.push(arr.slice(i, i += len)); - } - return chunks; - } - - $scope.groupingSort = function (item) { - if (!item.id) { - return ''; - } - - return item.name.toLowerCase(); - }; - - $scope.clipboardError = function (e) { - alert('Your web browser does not support easy clipboard copying. ' + - 'Edit the item and copy it manually instead.'); - }; - - $scope.editCipher = function (cipher) { - var editModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultEditCipher.html', - controller: 'vaultEditCipherController', - resolve: { - cipherId: function () { return cipher.id; } - } - }); - - editModel.result.then(function (returnVal) { - if (returnVal.action === 'edit') { - var index = $scope.ciphers.indexOf(cipher); - if (index > -1) { - // restore collection ids since those cannot change on edit here. - returnVal.data.collectionIds = $rootScope.vaultCiphers[index].collectionIds; - $rootScope.vaultCiphers[index] = returnVal.data; - } - sortScopedCipherData(); - } - else if (returnVal.action === 'partialEdit') { - cipher.folderId = returnVal.data.folderId; - cipher.favorite = returnVal.data.favorite; - } - else if (returnVal.action === 'delete') { - removeCipherFromScopes(cipher); - } - }); - }; - - $scope.$on('vaultAddCipher', function (event, args) { - $scope.addCipher(); - }); - - $scope.addCipher = function () { - var addModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultAddCipher.html', - controller: 'vaultAddCipherController', - resolve: { - selectedFolder: function () { return $scope.selectedFolder; }, - selectedType: function () { return $scope.selectedType; }, - checkedFavorite: function () { return $scope.selectedFavorites; } - } - }); - - addModel.result.then(function (addedCipher) { - $rootScope.vaultCiphers.push(addedCipher); - sortScopedCipherData(); - }); - }; - - $scope.deleteCipher = function (cipher) { - if (!confirm('Are you sure you want to delete this item (' + cipher.name + ')?')) { - return; - } - - apiService.ciphers.del({ id: cipher.id }, function () { - $analytics.eventTrack('Deleted Item'); - removeCipherFromScopes(cipher); - }); - }; - - $scope.attachments = function (cipher) { - authService.getUserProfile().then(function (profile) { - return { - isPremium: profile.premium, - orgUseStorage: cipher.organizationId && !!profile.organizations[cipher.organizationId].maxStorageGb - }; - }).then(function (perms) { - if (!cipher.hasAttachments) { - if (cipher.organizationId && !perms.orgUseStorage) { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/paidOrgRequired.html', - controller: 'paidOrgRequiredController', - resolve: { - orgId: function () { return cipher.organizationId; } - } - }); - return; - } - - if (!cipher.organizationId && !perms.isPremium) { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/premiumRequired.html', - controller: 'premiumRequiredController' - }); - return; - } - } - - if (!cipher.organizationId && !cryptoService.getEncKey()) { - toastr.error('You cannot use this feature until you update your encryption key.', 'Feature Unavailable'); - return; - } - - var attachmentModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultAttachments.html', - controller: 'vaultAttachmentsController', - resolve: { - cipherId: function () { return cipher.id; } - } - }); - - attachmentModel.result.then(function (hasAttachments) { - cipher.hasAttachments = hasAttachments; - }); - }); - }; - - $scope.editFolder = function (folder) { - if (!folder.id) { - return; - } - - var editModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultEditFolder.html', - controller: 'vaultEditFolderController', - size: 'sm', - resolve: { - folderId: function () { return folder.id; } - } - }); - - editModel.result.then(function (editedFolder) { - folder.name = editedFolder.name; - }); - }; - - $scope.$on('vaultAddFolder', function (event, args) { - $scope.addFolder(); - }); - - $scope.addFolder = function () { - var addModel = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultAddFolder.html', - controller: 'vaultAddFolderController', - size: 'sm' - }); - - addModel.result.then(function (addedFolder) { - $rootScope.vaultFolders.push(addedFolder); - }); - }; - - $scope.deleteFolder = function (folder) { - if (!folder.id) { - return; - } - - if (!confirm('Are you sure you want to delete this folder (' + folder.name + ')? ' + - 'Any items will be moved to "No Folder".')) { - return; - } - - apiService.folders.del({ id: folder.id }, function () { - $analytics.eventTrack('Deleted Folder'); - var index = $rootScope.vaultFolders.indexOf(folder); - if (index > -1) { - $rootScope.vaultFolders.splice(index, 1); - for(var i = 0; i < $rootScope.vaultCiphers.length; i++) { - if($rootScope.vaultCiphers[i].folderId === folder.id) { - $rootScope.vaultCiphers[i].folderId = null; - } - } - $scope.filterAll(); - } - }); - }; - - $scope.share = function (cipher) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultShareCipher.html', - controller: 'vaultShareCipherController', - resolve: { - cipherId: function () { return cipher.id; } - } - }); - - modal.result.then(function (returned) { - cipher.organizationId = returned.orgId; - cipher.collectionIds = returned.collectionIds || []; - }); - }; - - $scope.editCollections = function (cipher) { - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultCipherCollections.html', - controller: 'vaultCipherCollectionsController', - resolve: { - cipherId: function () { return cipher.id; } - } - }); - - modal.result.then(function (response) { - if (response.collectionIds && !response.collectionIds.length) { - removeCipherFromScopes(cipher); - } - else if (response.collectionIds) { - cipher.collectionIds = response.collectionIds; - } - }); - }; - - $scope.filterCollection = function (col) { - resetSelected(); - $scope.selectedCollection = col; - $scope.selectedIcon = 'fa-cube'; - $scope.filter = function (c) { - return c.collectionIds && c.collectionIds.indexOf(col.id) > -1; - }; - fixLayout(); - }; - - $scope.filterFolder = function (f) { - resetSelected(); - $scope.selectedFolder = f; - $scope.selectedIcon = 'fa-folder-open' + (!f.id ? '-o' : ''); - $scope.filter = function (c) { - return c.folderId === f.id; - }; - fixLayout(); - }; - - $scope.filterType = function (t) { - resetSelected(); - $scope.selectedType = t; - switch (t) { - case constants.cipherType.login: - $scope.selectedTitle = 'Login'; - $scope.selectedIcon = 'fa-globe'; - break; - case constants.cipherType.card: - $scope.selectedTitle = 'Card'; - $scope.selectedIcon = 'fa-credit-card'; - break; - case constants.cipherType.identity: - $scope.selectedTitle = 'Identity'; - $scope.selectedIcon = 'fa-id-card-o'; - break; - case constants.cipherType.secureNote: - $scope.selectedTitle = 'Secure Note'; - $scope.selectedIcon = 'fa-sticky-note-o'; - break; - default: - break; - } - $scope.filter = function (c) { - return c.type === t; - }; - fixLayout(); - }; - - $scope.filterFavorites = function () { - resetSelected(); - $scope.selectedFavorites = true; - $scope.selectedTitle = 'Favorites'; - $scope.selectedIcon = 'fa-star'; - $scope.filter = function (c) { - return !!c.favorite; - }; - fixLayout(); - }; - - $scope.filterAll = function () { - resetSelected(); - $scope.selectedAll = true; - $scope.selectedTitle = 'All'; - $scope.selectedIcon = 'fa-th'; - $scope.filter = null; - fixLayout(); - }; - - function resetSelected() { - $scope.selectedFolder = undefined; - $scope.selectedCollection = undefined; - $scope.selectedType = undefined; - $scope.selectedFavorites = false; - $scope.selectedAll = false; - } - - function fixLayout() { - if ($.AdminLTE && $.AdminLTE.layout) { - $timeout(function () { - $.AdminLTE.layout.fix(); - }, 0); - } - } - - $scope.cipherFilter = function () { - return function (cipher) { - return !$scope.filter || $scope.filter(cipher); - }; - }; - - $scope.unselectAll = function () { - selectAll(false); - }; - - $scope.selectAll = function () { - selectAll(true); - }; - - $scope.select = function ($event) { - var checkbox = $($event.currentTarget).closest('tr').find('input[name="cipherSelection"]'); - checkbox.prop('checked', !checkbox.prop('checked')); - }; - - function distinct(value, index, self) { - return self.indexOf(value) === index; - } - - function getSelectedCiphers() { - return $('input[name="cipherSelection"]:checked').map(function () { - return $(this).val(); - }).get().filter(distinct); - } - - function selectAll(select) { - $('input[name="cipherSelection"]').prop('checked', select); - } - - $scope.bulkMove = function () { - var ids = getSelectedCiphers(); - if (ids.length === 0) { - alert('You have not selected anything.'); - return; - } - - var modal = $uibModal.open({ - animation: true, - templateUrl: 'app/vault/views/vaultMoveCiphers.html', - controller: 'vaultMoveCiphersController', - size: 'sm', - resolve: { - ids: function () { return ids; } - } - }); - - modal.result.then(function (folderId) { - for (var i = 0; i < ids.length; i++) { - var cipher = $filter('filter')($rootScope.vaultCiphers, { id: ids[i] }); - if (cipher.length) { - cipher[0].folderId = folderId; - } - } - - selectAll(false); - sortScopedCipherData(); - toastr.success('Items have been moved!'); - }); - }; - - $scope.bulkDelete = function () { - var ids = getSelectedCiphers(); - if (ids.length === 0) { - alert('You have not selected anything.'); - return; - } - - if (!confirm('Are you sure you want to delete the selected items (total: ' + ids.length + ')?')) { - return; - } - - $scope.actionLoading = true; - apiService.ciphers.delMany({ ids: ids }, function () { - $analytics.eventTrack('Bulk Deleted Items'); - - for (var i = 0; i < ids.length; i++) { - var cipher = $filter('filter')($rootScope.vaultCiphers, { id: ids[i] }); - if (cipher.length && cipher[0].edit) { - removeCipherFromScopes(cipher[0]); - } - } - - selectAll(false); - $scope.actionLoading = false; - toastr.success('Items have been deleted!'); - }, function (e) { - var errors = validationService.parseErrors(e); - toastr.error(errors.length ? errors[0] : 'An error occurred.'); - $scope.actionLoading = false; - }); - }; - - function removeCipherFromScopes(cipher) { - var index = $rootScope.vaultCiphers.indexOf(cipher); - if (index > -1) { - $rootScope.vaultCiphers.splice(index, 1); - } - - index = $scope.ciphers.indexOf(cipher); - if (index > -1) { - $scope.ciphers.splice(index, 1); - } - } - }); diff --git a/src/app/vault/vaultEditCipherController.js b/src/app/vault/vaultEditCipherController.js deleted file mode 100644 index 635cdaddff..0000000000 --- a/src/app/vault/vaultEditCipherController.js +++ /dev/null @@ -1,180 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultEditCipherController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, - passwordService, cipherId, $analytics, $rootScope, authService, $uibModal, constants, $filter) { - $analytics.eventTrack('vaultEditCipherController', { category: 'Modal' }); - $scope.folders = $rootScope.vaultFolders; - $scope.cipher = {}; - $scope.readOnly = false; - $scope.constants = constants; - - authService.getUserProfile().then(function (profile) { - $scope.useTotp = profile.premium; - return apiService.ciphers.get({ id: cipherId }).$promise; - }).then(function (cipher) { - $scope.cipher = cipherService.decryptCipher(cipher); - $scope.readOnly = !$scope.cipher.edit; - $scope.useTotp = $scope.useTotp || $scope.cipher.organizationUseTotp; - setUriMatchValues(); - }); - - $scope.save = function (model) { - if ($scope.readOnly) { - $scope.savePromise = apiService.ciphers.putPartial({ id: cipherId }, { - folderId: model.folderId, - favorite: model.favorite - }, function (response) { - $analytics.eventTrack('Partially Edited Cipher'); - $uibModalInstance.close({ - action: 'partialEdit', - data: { - id: cipherId, - favorite: model.favorite, - folderId: model.folderId && model.folderId !== '' ? model.folderId : null - } - }); - }).$promise; - } - else { - var cipher = cipherService.encryptCipher(model, $scope.cipher.type); - $scope.savePromise = apiService.ciphers.put({ id: cipherId }, cipher, function (cipherResponse) { - $analytics.eventTrack('Edited Cipher'); - var decCipher = cipherService.decryptCipherPreview(cipherResponse); - $uibModalInstance.close({ - action: 'edit', - data: decCipher - }); - }).$promise; - } - }; - - $scope.generatePassword = function () { - if (!$scope.cipher.login.password || confirm('Are you sure you want to overwrite the current password?')) { - $analytics.eventTrack('Generated Password From Edit'); - $scope.cipher.login.password = passwordService.generatePassword({ length: 14, special: true }); - } - }; - - $scope.addUri = function () { - if (!$scope.cipher.login) { - return; - } - - if (!$scope.cipher.login.uris) { - $scope.cipher.login.uris = []; - } - - $scope.cipher.login.uris.push({ - uri: null, - match: null, - matchValue: null - }); - }; - - $scope.removeUri = function (uri) { - if (!$scope.cipher.login || !$scope.cipher.login.uris) { - return; - } - - var index = $scope.cipher.login.uris.indexOf(uri); - if (index > -1) { - $scope.cipher.login.uris.splice(index, 1); - } - }; - - $scope.uriMatchChanged = function (uri) { - if ((!uri.matchValue && uri.matchValue !== 0) || uri.matchValue === '') { - uri.match = null; - } - else { - uri.match = parseInt(uri.matchValue); - } - }; - - $scope.addField = function () { - if (!$scope.cipher.fields) { - $scope.cipher.fields = []; - } - - $scope.cipher.fields.push({ - type: constants.fieldType.text.toString(), - name: null, - value: null - }); - }; - - $scope.removeField = function (field) { - var index = $scope.cipher.fields.indexOf(field); - if (index > -1) { - $scope.cipher.fields.splice(index, 1); - } - }; - - $scope.toggleFavorite = function () { - $scope.cipher.favorite = !$scope.cipher.favorite; - }; - - $scope.clipboardSuccess = function (e) { - e.clearSelection(); - selectPassword(e); - }; - - $scope.clipboardError = function (e, password) { - if (password) { - selectPassword(e); - } - alert('Your web browser does not support easy clipboard copying. Copy it manually instead.'); - }; - - $scope.folderSort = function (item) { - if (!item.id) { - return ''; - } - - return item.name.toLowerCase(); - }; - - function selectPassword(e) { - var target = $(e.trigger).parent().prev(); - if (target.attr('type') === 'text') { - target.select(); - } - } - - $scope.delete = function () { - if (!confirm('Are you sure you want to delete this item (' + $scope.cipher.name + ')?')) { - return; - } - - apiService.ciphers.del({ id: $scope.cipher.id }, function () { - $analytics.eventTrack('Deleted Cipher From Edit'); - $uibModalInstance.close({ - action: 'delete', - data: $scope.cipher.id - }); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - $scope.showUpgrade = function () { - $uibModal.open({ - animation: true, - templateUrl: 'app/views/premiumRequired.html', - controller: 'premiumRequiredController' - }); - }; - - function setUriMatchValues() { - if ($scope.cipher.login && $scope.cipher.login.uris) { - for (var i = 0; i < $scope.cipher.login.uris.length; i++) { - $scope.cipher.login.uris[i].matchValue = - $scope.cipher.login.uris[i].match || $scope.cipher.login.uris[i].match === 0 ? - $scope.cipher.login.uris[i].match.toString() : ''; - } - } - } - }); diff --git a/src/app/vault/vaultEditFolderController.js b/src/app/vault/vaultEditFolderController.js deleted file mode 100644 index 438bfe439c..0000000000 --- a/src/app/vault/vaultEditFolderController.js +++ /dev/null @@ -1,25 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultEditFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, folderId, $analytics) { - $analytics.eventTrack('vaultEditFolderController', { category: 'Modal' }); - $scope.folder = {}; - - apiService.folders.get({ id: folderId }, function (folder) { - $scope.folder = cipherService.decryptFolder(folder); - }); - - $scope.savePromise = null; - $scope.save = function (model) { - var folder = cipherService.encryptFolder(model); - $scope.savePromise = apiService.folders.put({ id: folderId }, folder, function (response) { - $analytics.eventTrack('Edited Folder'); - var decFolder = cipherService.decryptFolder(response); - $uibModalInstance.close(decFolder); - }).$promise; - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/vault/vaultModule.js b/src/app/vault/vaultModule.js deleted file mode 100644 index 84125898a9..0000000000 --- a/src/app/vault/vaultModule.js +++ /dev/null @@ -1,2 +0,0 @@ -angular - .module('bit.vault', ['ui.bootstrap', 'ngclipboard']); diff --git a/src/app/vault/vaultMoveCiphersController.js b/src/app/vault/vaultMoveCiphersController.js deleted file mode 100644 index a4f13c3e22..0000000000 --- a/src/app/vault/vaultMoveCiphersController.js +++ /dev/null @@ -1,28 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultMoveCiphersController', function ($scope, apiService, $uibModalInstance, ids, $analytics, - $rootScope, $filter) { - $analytics.eventTrack('vaultMoveCiphersController', { category: 'Modal' }); - $scope.folders = $rootScope.vaultFolders; - $scope.count = ids.length; - - $scope.save = function () { - $scope.savePromise = apiService.ciphers.moveMany({ ids: ids, folderId: $scope.folderId }, function () { - $analytics.eventTrack('Bulk Moved Ciphers'); - $uibModalInstance.close($scope.folderId || null); - }).$promise; - }; - - $scope.folderSort = function (item) { - if (!item.id) { - return '!'; - } - - return item.name.toLowerCase(); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - }); diff --git a/src/app/vault/vaultShareCipherController.js b/src/app/vault/vaultShareCipherController.js deleted file mode 100644 index bb959e0eb0..0000000000 --- a/src/app/vault/vaultShareCipherController.js +++ /dev/null @@ -1,184 +0,0 @@ -angular - .module('bit.vault') - - .controller('vaultShareCipherController', function ($scope, apiService, $uibModalInstance, authService, cipherService, - cipherId, $analytics, $state, cryptoService, $q, toastr) { - $analytics.eventTrack('vaultShareCipherController', { category: 'Modal' }); - $scope.model = {}; - $scope.cipher = {}; - $scope.collections = []; - $scope.selectedCollections = {}; - $scope.organizations = []; - var organizationCollectionCounts = {}; - $scope.loadingCollections = true; - $scope.loading = true; - $scope.readOnly = false; - - apiService.ciphers.get({ id: cipherId }).$promise.then(function (cipher) { - $scope.readOnly = !cipher.Edit; - if (cipher.Edit) { - $scope.cipher = cipherService.decryptCipher(cipher); - } - - return cipher.Edit; - }).then(function (canEdit) { - $scope.loading = false; - if (!canEdit) { - return; - } - - return authService.getUserProfile(); - }).then(function (profile) { - if (profile && profile.organizations) { - var orgs = [], - setFirstOrg = false; - - for (var i in profile.organizations) { - if (profile.organizations.hasOwnProperty(i) && profile.organizations[i].enabled) { - orgs.push({ - id: profile.organizations[i].id, - name: profile.organizations[i].name - }); - - organizationCollectionCounts[profile.organizations[i].id] = 0; - - if (!setFirstOrg) { - setFirstOrg = true; - $scope.model.organizationId = profile.organizations[i].id; - } - } - } - - $scope.organizations = orgs; - - apiService.collections.listMe({ writeOnly: true }, function (response) { - var collections = []; - for (var i = 0; i < response.Data.length; i++) { - var decCollection = cipherService.decryptCollection(response.Data[i]); - decCollection.organizationId = response.Data[i].OrganizationId; - collections.push(decCollection); - organizationCollectionCounts[decCollection.organizationId]++; - } - - $scope.collections = collections; - $scope.loadingCollections = false; - }); - } - }); - - $scope.toggleCollectionSelectionAll = function ($event) { - var collections = {}; - if ($event.target.checked) { - for (var i = 0; i < $scope.collections.length; i++) { - if ($scope.model.organizationId && $scope.collections[i].organizationId === $scope.model.organizationId) { - collections[$scope.collections[i].id] = true; - } - } - } - - $scope.selectedCollections = collections; - }; - - $scope.toggleCollectionSelection = function (id) { - if (id in $scope.selectedCollections) { - delete $scope.selectedCollections[id]; - } - else { - $scope.selectedCollections[id] = true; - } - }; - - $scope.collectionSelected = function (collection) { - return collection.id in $scope.selectedCollections; - }; - - $scope.allSelected = function () { - if (!$scope.model.organizationId) { - return false; - } - - return Object.keys($scope.selectedCollections).length === organizationCollectionCounts[$scope.model.organizationId]; - }; - - $scope.orgChanged = function () { - $scope.selectedCollections = {}; - }; - - $scope.submitPromise = null; - $scope.submit = function (model) { - var orgKey = cryptoService.getOrgKey(model.organizationId); - - var errorOnUpload = false; - var attachmentSharePromises = []; - if ($scope.cipher.attachments) { - for (var i = 0; i < $scope.cipher.attachments.length; i++) { - /* jshint ignore:start */ - (function (attachment) { - var promise = cipherService.downloadAndDecryptAttachment(null, attachment, false) - .then(function (decData) { - return cryptoService.encryptToBytes(decData.buffer, orgKey); - }).then(function (encData) { - if (errorOnUpload) { - return; - } - - var fd = new FormData(); - var blob = new Blob([encData], { type: 'application/octet-stream' }); - var encFilename = cryptoService.encrypt(attachment.fileName, orgKey); - fd.append('data', blob, encFilename); - - return apiService.ciphers.postShareAttachment({ - id: cipherId, - attachmentId: attachment.id, - orgId: model.organizationId - }, fd).$promise; - }, function (err) { - errorOnUpload = true; - }); - attachmentSharePromises.push(promise); - })($scope.cipher.attachments[i]); - /* jshint ignore:end */ - } - } - - var returnedCollectionIds = null; - $scope.submitPromise = $q.all(attachmentSharePromises).then(function () { - if (errorOnUpload) { - return; - } - - $scope.cipher.organizationId = model.organizationId; - - var request = { - collectionIds: [], - cipher: cipherService.encryptCipher($scope.cipher, $scope.cipher.type, null, true) - }; - - for (var id in $scope.selectedCollections) { - if ($scope.selectedCollections.hasOwnProperty(id)) { - request.collectionIds.push(id); - } - } - - returnedCollectionIds = request.collectionIds; - return apiService.ciphers.putShare({ id: cipherId }, request).$promise; - }).then(function (response) { - $analytics.eventTrack('Shared Cipher'); - toastr.success('Item has been shared.'); - $uibModalInstance.close({ - orgId: model.organizationId, - collectionIds: returnedCollectionIds - }); - }); - }; - - $scope.close = function () { - $uibModalInstance.dismiss('cancel'); - }; - - $scope.createOrg = function () { - $state.go('backend.user.settingsCreateOrg').then(function () { - $uibModalInstance.dismiss('cancel'); - }); - }; - }); diff --git a/src/app/vault/views/vault.html b/src/app/vault/views/vault.html deleted file mode 100644 index 49b8e90a13..0000000000 --- a/src/app/vault/views/vault.html +++ /dev/null @@ -1,235 +0,0 @@ -
- -

- My Vault - - , - , & - - -

-
-
-
-

Loading...

-
-
-
-

- - {{selectedFolder ? selectedFolder.name : selectedCollection ? selectedCollection.name : selectedTitle}} - -

-
- -
-
-
-
-

No items to list.

- -
-
- - - - - - - - - -
- - - - - - - - {{cipher.name}} - - - -
- {{cipher.subTitle}} -
-
-
-
-
- diff --git a/src/app/vault/views/vaultAddCipher.html b/src/app/vault/views/vaultAddCipher.html deleted file mode 100644 index 13ed776d29..0000000000 --- a/src/app/vault/views/vaultAddCipher.html +++ /dev/null @@ -1,616 +0,0 @@ - -
- - -
diff --git a/src/app/vault/views/vaultAddFolder.html b/src/app/vault/views/vaultAddFolder.html deleted file mode 100644 index 91a181337d..0000000000 --- a/src/app/vault/views/vaultAddFolder.html +++ /dev/null @@ -1,24 +0,0 @@ - -
- - -
\ No newline at end of file diff --git a/src/app/vault/views/vaultAttachments.html b/src/app/vault/views/vaultAttachments.html deleted file mode 100644 index 75f9f12356..0000000000 --- a/src/app/vault/views/vaultAttachments.html +++ /dev/null @@ -1,75 +0,0 @@ - -
- - -
diff --git a/src/app/vault/views/vaultCipherCollections.html b/src/app/vault/views/vaultCipherCollections.html deleted file mode 100644 index 6f72f89b5a..0000000000 --- a/src/app/vault/views/vaultCipherCollections.html +++ /dev/null @@ -1,55 +0,0 @@ - -
- - -
\ No newline at end of file diff --git a/src/app/vault/views/vaultEditCipher.html b/src/app/vault/views/vaultEditCipher.html deleted file mode 100644 index 4f0d0e0158..0000000000 --- a/src/app/vault/views/vaultEditCipher.html +++ /dev/null @@ -1,621 +0,0 @@ - -
- - -
diff --git a/src/app/vault/views/vaultEditFolder.html b/src/app/vault/views/vaultEditFolder.html deleted file mode 100644 index be6d34eb5e..0000000000 --- a/src/app/vault/views/vaultEditFolder.html +++ /dev/null @@ -1,24 +0,0 @@ - -
- - -
\ No newline at end of file diff --git a/src/app/vault/views/vaultMoveCiphers.html b/src/app/vault/views/vaultMoveCiphers.html deleted file mode 100644 index afef7db698..0000000000 --- a/src/app/vault/views/vaultMoveCiphers.html +++ /dev/null @@ -1,34 +0,0 @@ - -
- - -
diff --git a/src/app/vault/views/vaultShareCipher.html b/src/app/vault/views/vaultShareCipher.html deleted file mode 100644 index 99938443e2..0000000000 --- a/src/app/vault/views/vaultShareCipher.html +++ /dev/null @@ -1,75 +0,0 @@ - -
- - -
diff --git a/src/app/views/backendLayout.html b/src/app/views/backendLayout.html deleted file mode 100644 index cd076260db..0000000000 --- a/src/app/views/backendLayout.html +++ /dev/null @@ -1,10 +0,0 @@ -
-
- -
- - Copyright © , 8bit Solutions LLC -
-
diff --git a/src/app/views/frontendLayout.html b/src/app/views/frontendLayout.html deleted file mode 100644 index 47e1b0a201..0000000000 --- a/src/app/views/frontendLayout.html +++ /dev/null @@ -1,2 +0,0 @@ -
-
\ No newline at end of file diff --git a/src/app/views/organizationLayout.html b/src/app/views/organizationLayout.html deleted file mode 100644 index 934495ee89..0000000000 --- a/src/app/views/organizationLayout.html +++ /dev/null @@ -1,110 +0,0 @@ -
- - -
- - - -
-
diff --git a/src/app/views/paidOrgRequired.html b/src/app/views/paidOrgRequired.html deleted file mode 100644 index 1452976a0e..0000000000 --- a/src/app/views/paidOrgRequired.html +++ /dev/null @@ -1,13 +0,0 @@ - - - \ No newline at end of file diff --git a/src/app/views/premiumRequired.html b/src/app/views/premiumRequired.html deleted file mode 100644 index 38939f064c..0000000000 --- a/src/app/views/premiumRequired.html +++ /dev/null @@ -1,36 +0,0 @@ - - - \ No newline at end of file diff --git a/src/app/views/userLayout.html b/src/app/views/userLayout.html deleted file mode 100644 index 0f7d1dc3d6..0000000000 --- a/src/app/views/userLayout.html +++ /dev/null @@ -1,160 +0,0 @@ -
- - -
- - - -
-
-

Update Your Browser

- You are using an unsupported web browser. The web vault may not function properly. - Update your browser now. -
-
-

Update Your Encryption Key

- You are currently using an outdated encryption scheme. - Learn more and update now. -
-
-

Verify Your Email

-
- Verify your account's email address to unlock access to all features. - Send verification email now. - -
-
- Check your email inbox for a verification link. - Send verification email again. - -
-
-
-
diff --git a/src/connectors/duo.html b/src/connectors/duo.html new file mode 100644 index 0000000000..31a48887ec --- /dev/null +++ b/src/connectors/duo.html @@ -0,0 +1,12 @@ + + + + + + + Bitwarden Duo Connector + + + + + diff --git a/src/connectors/duo.scss b/src/connectors/duo.scss new file mode 100644 index 0000000000..8f5c0373bc --- /dev/null +++ b/src/connectors/duo.scss @@ -0,0 +1,17 @@ +html, body { + margin: 0; + padding: 0; +} + +body { + background: #efeff4 url('../images/loading.svg') 0 0 no-repeat; +} + +iframe { + display: block; + width: 100%; + height: 400px; + border: none; + margin: 0; + padding: 0; +} diff --git a/src/connectors/duo.ts b/src/connectors/duo.ts new file mode 100644 index 0000000000..c9947e360d --- /dev/null +++ b/src/connectors/duo.ts @@ -0,0 +1,50 @@ +import * as DuoWebSDK from 'jslib/misc/duo'; + +// tslint:disable-next-line +require('./duo.scss'); + +document.addEventListener('DOMContentLoaded', (event) => { + const frameElement = document.createElement('iframe'); + frameElement.setAttribute('id', 'duo_iframe'); + setFrameHeight(); + document.body.appendChild(frameElement); + + const hostParam = getQsParam('host'); + const requestParam = getQsParam('request'); + DuoWebSDK.init({ + iframe: 'duo_iframe', + host: hostParam, + sig_request: requestParam, + submit_callback: (form: any) => { + invokeCSCode(form.elements.sig_response.value); + }, + }); + + window.onresize = setFrameHeight; + + function setFrameHeight() { + frameElement.style.height = window.innerHeight + 'px'; + } +}); + +function getQsParam(name: string) { + const url = window.location.href; + name = name.replace(/[\[\]]/g, '\\$&'); + const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'); + const results = regex.exec(url); + + if (!results) { + return null; + } + if (!results[2]) { + return ''; + } + + return decodeURIComponent(results[2].replace(/\+/g, ' ')); +} + +function invokeCSCode(data: string) { + try { + (window as any).invokeCSharpAction(data); + } catch (err) { } +} diff --git a/src/connectors/u2f.html b/src/connectors/u2f.html new file mode 100644 index 0000000000..f1151bfca9 --- /dev/null +++ b/src/connectors/u2f.html @@ -0,0 +1,12 @@ + + + + + + Bitwarden U2F Connector + + + + + + diff --git a/src/js/u2f-connector.js b/src/connectors/u2f.js similarity index 96% rename from src/js/u2f-connector.js rename to src/connectors/u2f.js index c09b33fdf8..d397af2e25 100644 --- a/src/js/u2f-connector.js +++ b/src/connectors/u2f.js @@ -1,4 +1,6 @@ -document.addEventListener('DOMContentLoaded', function (event) { +import * as u2f from 'u2f'; + +document.addEventListener('DOMContentLoaded', function (event) { init(); }); diff --git a/src/duo-connector.html b/src/duo-connector.html deleted file mode 100644 index 7de0ae63bc..0000000000 --- a/src/duo-connector.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - Duo Two-step Login - - - - - - - diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000000..4859a0869e --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,2 @@ +declare function escape(s: string): string; +declare function unescape(s: string): string; diff --git a/src/images/boxed-bg-2x.png b/src/images/boxed-bg-2x.png deleted file mode 100644 index 2050e8aa04..0000000000 Binary files a/src/images/boxed-bg-2x.png and /dev/null differ diff --git a/src/images/boxed-bg.png b/src/images/boxed-bg.png deleted file mode 100644 index da898fc3cb..0000000000 Binary files a/src/images/boxed-bg.png and /dev/null differ diff --git a/src/images/cards.png b/src/images/cards.png index 8cf6738760..16722411c1 100644 Binary files a/src/images/cards.png and b/src/images/cards.png differ diff --git a/src/images/logo-dark@2x.png b/src/images/logo-dark@2x.png new file mode 100644 index 0000000000..0266e85122 Binary files /dev/null and b/src/images/logo-dark@2x.png differ diff --git a/src/images/two-factor/authapp.png b/src/images/two-factor/0.png similarity index 100% rename from src/images/two-factor/authapp.png rename to src/images/two-factor/0.png diff --git a/src/images/two-factor/gmail.png b/src/images/two-factor/1.png similarity index 100% rename from src/images/two-factor/gmail.png rename to src/images/two-factor/1.png diff --git a/src/images/two-factor/duo.png b/src/images/two-factor/2.png similarity index 100% rename from src/images/two-factor/duo.png rename to src/images/two-factor/2.png diff --git a/src/images/two-factor/yubico.png b/src/images/two-factor/3.png similarity index 100% rename from src/images/two-factor/yubico.png rename to src/images/two-factor/3.png diff --git a/src/images/two-factor/fido.png b/src/images/two-factor/4.png similarity index 100% rename from src/images/two-factor/fido.png rename to src/images/two-factor/4.png diff --git a/src/images/two-factor/6.png b/src/images/two-factor/6.png new file mode 100644 index 0000000000..ab2e434036 Binary files /dev/null and b/src/images/two-factor/6.png differ diff --git a/src/images/two-factor/u2fkey.jpg b/src/images/u2fkey.jpg similarity index 100% rename from src/images/two-factor/u2fkey.jpg rename to src/images/u2fkey.jpg diff --git a/src/images/two-factor/yubikey.jpg b/src/images/yubikey.jpg similarity index 100% rename from src/images/two-factor/yubikey.jpg rename to src/images/yubikey.jpg diff --git a/src/index.html b/src/index.html index ec025538df..ac990855c7 100644 --- a/src/index.html +++ b/src/index.html @@ -1,249 +1,35 @@  - + + - - + - + Bitwarden Web Vault - - - - - - - - - - - - + + - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +
+
+ +

+ +

+
+
+
+ diff --git a/src/js/analytics.js b/src/js/analytics.js deleted file mode 100644 index 3cab7e7a8a..0000000000 --- a/src/js/analytics.js +++ /dev/null @@ -1,10 +0,0 @@ -// @if !selfHosted -(function (i, s, o, g, r, a, m) { - i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () { - (i[r].q = i[r].q || []).push(arguments) - }, i[r].l = 1 * new Date(); a = s.createElement(o), - m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) -})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); - -ga('create', 'UA-81915606-3', 'auto'); -// @endif diff --git a/src/js/duo-connector.js b/src/js/duo-connector.js deleted file mode 100644 index c4f1d60107..0000000000 --- a/src/js/duo-connector.js +++ /dev/null @@ -1,40 +0,0 @@ -!(function () { - var frameElement = document.createElement('iframe'); - frameElement.setAttribute('id', 'duo_iframe'); - setFrameHeight(); - document.body.appendChild(frameElement); - - var hostParam = getQsParam('host'); - var requestParam = getQsParam('request'); - Duo.init({ - host: hostParam, - sig_request: requestParam, - submit_callback: function (form) { - invokeCSCode(form.elements.sig_response.value); - } - }); - - window.onresize = setFrameHeight; - function setFrameHeight() { - frameElement.style.height = window.innerHeight + 'px'; - } -})(); - -function getQsParam(name) { - var url = window.location.href; - name = name.replace(/[\[\]]/g, '\\$&'); - var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); -} - -function invokeCSCode(data) { - try { - invokeCSharpAction(data); - } - catch (err) { - - } -} diff --git a/src/js/duo.js b/src/js/duo.js deleted file mode 100644 index bb0f58a787..0000000000 --- a/src/js/duo.js +++ /dev/null @@ -1,430 +0,0 @@ -/** - * Duo Web SDK v2 - * Copyright 2017, Duo Security - */ - -(function (root, factory) { - /*eslint-disable */ - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define([], factory); - /*eslint-enable */ - } else if (typeof module === 'object' && module.exports) { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - // Browser globals (root is window) - var Duo = factory(); - // If the Javascript was loaded via a script tag, attempt to autoload - // the frame. - Duo._onReady(Duo.init); - - // Attach Duo to the `window` object - root.Duo = Duo; - } -}(this, function() { - var DUO_MESSAGE_FORMAT = /^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/; - var DUO_ERROR_FORMAT = /^ERR\|[\w\s\.\(\)]+$/; - var DUO_OPEN_WINDOW_FORMAT = /^DUO_OPEN_WINDOW\|/; - var VALID_OPEN_WINDOW_DOMAINS = [ - 'duo.com', - 'duosecurity.com', - 'duomobile.s3-us-west-1.amazonaws.com' - ]; - - var iframeId = 'duo_iframe', - postAction = '', - postArgument = 'sig_response', - host, - sigRequest, - duoSig, - appSig, - iframe, - submitCallback; - - function throwError(message, url) { - throw new Error( - 'Duo Web SDK error: ' + message + - (url ? ('\n' + 'See ' + url + ' for more information') : '') - ); - } - - function hyphenize(str) { - return str.replace(/([a-z])([A-Z])/, '$1-$2').toLowerCase(); - } - - // cross-browser data attributes - function getDataAttribute(element, name) { - if ('dataset' in element) { - return element.dataset[name]; - } else { - return element.getAttribute('data-' + hyphenize(name)); - } - } - - // cross-browser event binding/unbinding - function on(context, event, fallbackEvent, callback) { - if ('addEventListener' in window) { - context.addEventListener(event, callback, false); - } else { - context.attachEvent(fallbackEvent, callback); - } - } - - function off(context, event, fallbackEvent, callback) { - if ('removeEventListener' in window) { - context.removeEventListener(event, callback, false); - } else { - context.detachEvent(fallbackEvent, callback); - } - } - - function onReady(callback) { - on(document, 'DOMContentLoaded', 'onreadystatechange', callback); - } - - function offReady(callback) { - off(document, 'DOMContentLoaded', 'onreadystatechange', callback); - } - - function onMessage(callback) { - on(window, 'message', 'onmessage', callback); - } - - function offMessage(callback) { - off(window, 'message', 'onmessage', callback); - } - - /** - * Parse the sig_request parameter, throwing errors if the token contains - * a server error or if the token is invalid. - * - * @param {String} sig Request token - */ - function parseSigRequest(sig) { - if (!sig) { - // nothing to do - return; - } - - // see if the token contains an error, throwing it if it does - if (sig.indexOf('ERR|') === 0) { - throwError(sig.split('|')[1]); - } - - // validate the token - if (sig.indexOf(':') === -1 || sig.split(':').length !== 2) { - throwError( - 'Duo was given a bad token. This might indicate a configuration ' + - 'problem with one of Duo\'s client libraries.', - 'https://www.duosecurity.com/docs/duoweb#first-steps' - ); - } - - var sigParts = sig.split(':'); - - // hang on to the token, and the parsed duo and app sigs - sigRequest = sig; - duoSig = sigParts[0]; - appSig = sigParts[1]; - - return { - sigRequest: sig, - duoSig: sigParts[0], - appSig: sigParts[1] - }; - } - - /** - * This function is set up to run when the DOM is ready, if the iframe was - * not available during `init`. - */ - function onDOMReady() { - iframe = document.getElementById(iframeId); - - if (!iframe) { - throw new Error( - 'This page does not contain an iframe for Duo to use.' + - 'Add an element like ' + - 'to this page. ' + - 'See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe ' + - 'for more information.' - ); - } - - // we've got an iframe, away we go! - ready(); - - // always clean up after yourself - offReady(onDOMReady); - } - - /** - * Validate that a MessageEvent came from the Duo service, and that it - * is a properly formatted payload. - * - * The Google Chrome sign-in page injects some JS into pages that also - * make use of postMessage, so we need to do additional validation above - * and beyond the origin. - * - * @param {MessageEvent} event Message received via postMessage - */ - function isDuoMessage(event) { - return Boolean( - event.origin === ('https://' + host) && - typeof event.data === 'string' && - ( - event.data.match(DUO_MESSAGE_FORMAT) || - event.data.match(DUO_ERROR_FORMAT) || - event.data.match(DUO_OPEN_WINDOW_FORMAT) - ) - ); - } - - /** - * Validate the request token and prepare for the iframe to become ready. - * - * All options below can be passed into an options hash to `Duo.init`, or - * specified on the iframe using `data-` attributes. - * - * Options specified using the options hash will take precedence over - * `data-` attributes. - * - * Example using options hash: - * ```javascript - * Duo.init({ - * iframe: "some_other_id", - * host: "api-main.duo.test", - * sig_request: "...", - * post_action: "/auth", - * post_argument: "resp" - * }); - * ``` - * - * Example using `data-` attributes: - * ``` - * - * ``` - * - * @param {Object} options - * @param {String} options.iframe The iframe, or id of an iframe to set up - * @param {String} options.host Hostname - * @param {String} options.sig_request Request token - * @param {String} [options.post_action=''] URL to POST back to after successful auth - * @param {String} [options.post_argument='sig_response'] Parameter name to use for response token - * @param {Function} [options.submit_callback] If provided, duo will not submit the form instead execute - * the callback function with reference to the "duo_form" form object - * submit_callback can be used to prevent the webpage from reloading. - */ - function init(options) { - if (options) { - if (options.host) { - host = options.host; - } - - if (options.sig_request) { - parseSigRequest(options.sig_request); - } - - if (options.post_action) { - postAction = options.post_action; - } - - if (options.post_argument) { - postArgument = options.post_argument; - } - - if (options.iframe) { - if (options.iframe.tagName) { - iframe = options.iframe; - } else if (typeof options.iframe === 'string') { - iframeId = options.iframe; - } - } - - if (typeof options.submit_callback === 'function') { - submitCallback = options.submit_callback; - } - } - - // if we were given an iframe, no need to wait for the rest of the DOM - if (false && iframe) { - ready(); - } else { - // try to find the iframe in the DOM - iframe = document.getElementById(iframeId); - - // iframe is in the DOM, away we go! - if (iframe) { - ready(); - } else { - // wait until the DOM is ready, then try again - onReady(onDOMReady); - } - } - - // always clean up after yourself! - offReady(init); - } - - /** - * This function is called when a message was received from another domain - * using the `postMessage` API. Check that the event came from the Duo - * service domain, and that the message is a properly formatted payload, - * then perform the post back to the primary service. - * - * @param event Event object (contains origin and data) - */ - function onReceivedMessage(event) { - if (isDuoMessage(event)) { - if (event.data.match(DUO_OPEN_WINDOW_FORMAT)) { - var url = event.data.substring("DUO_OPEN_WINDOW|".length); - if (isValidUrlToOpen(url)) { - // Open the URL that comes after the DUO_WINDOW_OPEN token. - window.open(url, "_self"); - } - } - else { - // the event came from duo, do the post back - doPostBack(event.data); - - // always clean up after yourself! - offMessage(onReceivedMessage); - } - } - } - - /** - * Validate that this passed in URL is one that we will actually allow to - * be opened. - * @param url String URL that the message poster wants to open - * @returns {boolean} true if we allow this url to be opened in the window - */ - function isValidUrlToOpen(url) { - if (!url) { - return false; - } - - var parser = document.createElement('a'); - parser.href = url; - - if (parser.protocol === "duotrustedendpoints:") { - return true; - } else if (parser.protocol !== "https:") { - return false; - } - - for (var i = 0; i < VALID_OPEN_WINDOW_DOMAINS.length; i++) { - if (parser.hostname.endsWith("." + VALID_OPEN_WINDOW_DOMAINS[i]) || - parser.hostname === VALID_OPEN_WINDOW_DOMAINS[i]) { - return true; - } - } - return false; - } - - /** - * Point the iframe at Duo, then wait for it to postMessage back to us. - */ - function ready() { - if (!host) { - host = getDataAttribute(iframe, 'host'); - - if (!host) { - throwError( - 'No API hostname is given for Duo to use. Be sure to pass ' + - 'a `host` parameter to Duo.init, or through the `data-host` ' + - 'attribute on the iframe element.', - 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' - ); - } - } - - if (!duoSig || !appSig) { - parseSigRequest(getDataAttribute(iframe, 'sigRequest')); - - if (!duoSig || !appSig) { - throwError( - 'No valid signed request is given. Be sure to give the ' + - '`sig_request` parameter to Duo.init, or use the ' + - '`data-sig-request` attribute on the iframe element.', - 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' - ); - } - } - - // if postAction/Argument are defaults, see if they are specified - // as data attributes on the iframe - if (postAction === '') { - postAction = getDataAttribute(iframe, 'postAction') || postAction; - } - - if (postArgument === 'sig_response') { - postArgument = getDataAttribute(iframe, 'postArgument') || postArgument; - } - - // point the iframe at Duo - iframe.src = [ - 'https://', host, '/frame/web/v1/auth?tx=', duoSig, - '&parent=', encodeURIComponent(document.location.href), - '&v=2.6' - ].join(''); - - // listen for the 'message' event - onMessage(onReceivedMessage); - } - - /** - * We received a postMessage from Duo. POST back to the primary service - * with the response token, and any additional user-supplied parameters - * given in form#duo_form. - */ - function doPostBack(response) { - // create a hidden input to contain the response token - var input = document.createElement('input'); - input.type = 'hidden'; - input.name = postArgument; - input.value = response + ':' + appSig; - - // user may supply their own form with additional inputs - var form = document.getElementById('duo_form'); - - // if the form doesn't exist, create one - if (!form) { - form = document.createElement('form'); - - // insert the new form after the iframe - iframe.parentElement.insertBefore(form, iframe.nextSibling); - } - - // make sure we are actually posting to the right place - form.method = 'POST'; - form.action = postAction; - - // add the response token input to the form - form.appendChild(input); - - // away we go! - if (typeof submitCallback === "function") { - submitCallback.call(null, form); - } else { - form.submit(); - } - } - - return { - init: init, - _onReady: onReady, - _parseSigRequest: parseSigRequest, - _isDuoMessage: isDuoMessage, - _doPostBack: doPostBack - }; -})); diff --git a/src/js/fallback-scripts.js b/src/js/fallback-scripts.js deleted file mode 100644 index 76f50c1318..0000000000 --- a/src/js/fallback-scripts.js +++ /dev/null @@ -1,9 +0,0 @@ -function loadScriptIfMissing(condition, path) { - if (!condition) { - document.write(' - - - - diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..d753ada085 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "noImplicitAny": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "target": "es5", + "lib": ["es5", "es6", "dom"], + "allowJs": true, + "sourceMap": true, + "types": [], + "baseUrl": ".", + "paths": { + "jslib/*": [ "jslib/src/*" ], + "@angular/*": [ "node_modules/@angular/*" ], + "angular2-toaster": [ "node_modules/angular2-toaster" ], + "angulartics2": [ "node_modules/angulartics2" ] + } + }, + "exclude": [ + "node_modules", + "dist", + "build", + "jslib/dist", + "jslib/spec", + "jslib/src/electron", + "jslib/src/services/nodeApi.service.ts", + "jslib/src/services/lowdbStorage.service.ts", + "jslib/src/misc/nodeUtils.ts", + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000..7e4320f723 --- /dev/null +++ b/tslint.json @@ -0,0 +1,54 @@ +{ + "extends": "tslint:recommended", + "rules": { + "align": [ true, "statements", "members" ], + "ban-types": { + "options": [ + [ "Object", "Avoid using the `Object` type. Did you mean `object`?" ], + [ "Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?" ], + [ "Number", "Avoid using the `Number` type. Did you mean `number`?" ], + [ "String", "Avoid using the `String` type. Did you mean `string`?" ], + [ "Symbol", "Avoid using the `Symbol` type. Did you mean `symbol`?" ] + ] + }, + "member-access": [ true, "no-public" ], + "member-ordering": [ + true, + { + "order": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "public-instance-field", + "protected-instance-field", + "private-instance-field", + "public-constructor", + "protected-constructor", + "private-constructor", + "public-instance-method", + "protected-instance-method", + "private-instance-method" + ] + } + ], + "no-empty": [ true, "allow-empty-catch" ], + "object-literal-sort-keys": false, + "object-literal-shorthand": [ true, "never" ], + "prefer-for-of": false, + "quotemark": [ true, "single" ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-module", + "check-operator", + "check-preblock", + "check-separator", + "check-type" + ], + "max-classes-per-file": false + } +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000000..00875aed14 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,174 @@ +const path = require('path'); +const fs = require('fs'); +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 AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin; +const pjson = require('./package.json'); + +if (process.env.NODE_ENV == null) { + process.env.NODE_ENV = 'development'; +} +const ENV = process.env.ENV = process.env.NODE_ENV; + +if (process.env.NODE_ENV == null) { + process.env.NODE_ENV = 'development'; +} + +const isVendorModule = (module) => { + if (!module.context) { + return false; + } + return module.context.indexOf('node_modules') !== -1; +}; + +const extractCss = new ExtractTextPlugin({ + filename: '[name].css', + disable: false, + allChunks: true, +}); + +const moduleRules = [ + { + test: /\.ts$/, + enforce: 'pre', + loader: 'tslint-loader', + }, + { + test: /\.(html)$/, + loader: 'html-loader', + }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + exclude: /.*(fontawesome-webfont)\.svg/, + use: [{ + loader: 'file-loader', + options: { + name: '[name].[ext]', + outputPath: 'images/', + } + }] + }, + { + test: /\.scss$/, + use: extractCss.extract({ + use: [ + { + loader: 'css-loader', + }, + { + loader: 'sass-loader', + }, + ], + publicPath: '../', + }), + }, + // Hide System.import warnings. ref: https://github.com/angular/angular/issues/21560 + { + test: /[\/\\]@angular[\/\\].+\.js$/, + parser: { system: true } + }, +]; + +const plugins = [ + new CleanWebpackPlugin([ + path.resolve(__dirname, 'build/*'), + ]), + // ref: https://github.com/angular/angular/issues/20357 + new webpack.ContextReplacementPlugin(/\@angular(\\|\/)core(\\|\/)esm5/, + path.resolve(__dirname, './src')), + new HtmlWebpackPlugin({ + template: './src/index.html', + filename: 'index.html', + chunks: ['app/polyfills', 'app/main'], + }), + new HtmlWebpackPlugin({ + template: './src/connectors/duo.html', + filename: 'duo-connector.html', + chunks: ['connectors/duo'], + }), + new HtmlWebpackPlugin({ + template: './src/connectors/u2f.html', + filename: 'u2f-connector.html', + chunks: ['connectors/u2f'], + }), + new CopyWebpackPlugin([ + { from: './src/manifest.json' }, + { from: './src/favicon.ico' }, + { from: './src/version.json' }, + { from: './src/browserconfig.xml' }, + { from: './src/app-id.json' }, + { from: './src/images', to: 'images' }, + { from: './src/locales', to: 'locales' }, + { from: './src/scripts', to: 'scripts' }, + ]), + extractCss, + new webpack.DefinePlugin({ + 'process.env': { + 'ENV': JSON.stringify(ENV), + 'SELF_HOST': JSON.stringify(process.env.SELF_HOST === 'true' ? true : false), + 'APPLICATION_VERSION': JSON.stringify(pjson.version), + 'CACHE_TAG': JSON.stringify(Math.random().toString(36).substring(7)), + } + }), +]; + +if (ENV === 'production') { + moduleRules.push({ + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + loader: '@ngtools/webpack', + }); + plugins.push(new AngularCompilerPlugin({ + tsConfigPath: 'tsconfig.json', + entryModule: 'src/app/app.module#AppModule', + sourceMap: true, + })); +} else { + moduleRules.push({ + test: /\.ts$/, + loaders: ['ts-loader', 'angular2-template-loader'], + exclude: path.resolve(__dirname, 'node_modules'), + }); +} + +let certSuffix = fs.existsSync('dev-server.local.pem') ? '.local' : '.shared'; +const serve = { + https: { + key: fs.readFileSync('dev-server' + certSuffix + '.pem'), + cert: fs.readFileSync('dev-server' + certSuffix + '.pem'), + }, + hot: false, +}; + +const config = { + mode: ENV, + devtool: 'source-map', + serve: serve, + entry: { + 'app/polyfills': './src/app/polyfills.ts', + 'app/main': './src/app/main.ts', + 'connectors/u2f': './src/connectors/u2f.js', + 'connectors/duo': './src/connectors/duo.ts', + }, + externals: { + 'u2f': 'u2f', + }, + resolve: { + extensions: ['.ts', '.js'], + alias: { + jslib: path.join(__dirname, 'jslib/src'), + }, + symlinks: false, + modules: [path.resolve('node_modules')], + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, 'build'), + }, + module: { rules: moduleRules }, + plugins: plugins, +}; + +module.exports = config;