diff --git a/dist/.publish b/dist/.publish deleted file mode 160000 index be3a93a5..00000000 --- a/dist/.publish +++ /dev/null @@ -1 +0,0 @@ -Subproject commit be3a93a58193fb727b597657ef40aac9395b5f36 diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 070c5c08..00000000 --- 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/settings.Preview.json b/settings.Preview.json deleted file mode 100644 index aaf40b8a..00000000 --- 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 e1b4909f..00000000 --- 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 9029e0ca..00000000 --- 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 94a86362..00000000 --- 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 418e9689..00000000 --- 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 dfa7f48b..00000000 --- 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 8ff0164e..00000000 --- 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 b26a2436..00000000 --- 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 d5db279e..00000000 --- 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 a6cc7bb5..00000000 --- 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 ebe9197b..00000000 --- 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 15c17910..00000000 --- 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 8abcd366..00000000 --- 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 e5a056e7..00000000 --- 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/views/accountsLogin.html b/src/app/accounts/views/accountsLogin.html deleted file mode 100644 index 5775b44a..00000000 --- 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 af9d0ec8..00000000 --- a/src/app/accounts/views/accountsLoginInfo.html +++ /dev/null @@ -1,49 +0,0 @@ -

Log in to access your vault.

-
-
-

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 744c9ea7..00000000 --- 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 d66e6068..00000000 --- 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 87b9757d..00000000 --- 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 861a3766..00000000 --- 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 fb97049c..00000000 --- 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 7b3434be..00000000 --- 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 7efd3309..00000000 --- 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 7bd695ea..00000000 --- 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 0821995c..00000000 --- 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 76a79c22..00000000 --- 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.js b/src/app/app.js deleted file mode 100644 index 496bb2ac..00000000 --- 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/config.js b/src/app/config.js deleted file mode 100644 index 0b665f3f..00000000 --- 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 24797a40..00000000 --- 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 a053712a..00000000 --- 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 b1842cf2..00000000 --- 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 ad4865f1..00000000 --- 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 1df1015e..00000000 --- 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 774f6a18..00000000 --- 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 f80d6d7c..00000000 --- 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 a5fc2bdd..00000000 --- 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 15b6e86f..00000000 --- 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 67f36267..00000000 --- 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 edbcbe62..00000000 --- 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 5b0f6060..00000000 --- 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 965c924e..00000000 --- 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/filters/enumLabelClassFilter.js b/src/app/filters/enumLabelClassFilter.js deleted file mode 100644 index 84a5d57b..00000000 --- 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 5678c497..00000000 --- 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 02c0dc59..00000000 --- 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 9af6c4b9..00000000 --- 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 a6878c43..00000000 --- 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 e303d542..00000000 --- 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 9b870eb8..00000000 --- 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 287e60d6..00000000 --- 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 521f9b5d..00000000 --- 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/organization/organizationBillingAdjustSeatsController.js b/src/app/organization/organizationBillingAdjustSeatsController.js deleted file mode 100644 index 8aa31d15..00000000 --- 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 7363da1b..00000000 --- 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 8b31b045..00000000 --- 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 bf587a57..00000000 --- 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 88c09f5f..00000000 --- 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 0b8d3ba2..00000000 --- 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 9489ebbc..00000000 --- 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 a8516a97..00000000 --- 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 880d3932..00000000 --- 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 26bb0f22..00000000 --- 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 7b230671..00000000 --- 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 2ad7f5f7..00000000 --- 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 9ec08781..00000000 --- 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 9857cb93..00000000 --- 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 8d0bf031..00000000 --- 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 7ff81d21..00000000 --- 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 bdaaf071..00000000 --- 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 4b3f1188..00000000 --- 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 0880ae47..00000000 --- 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 46195dc7..00000000 --- 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 c35a8d38..00000000 --- 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 02a56936..00000000 --- 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 25c90842..00000000 --- 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 80114e82..00000000 --- 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 1128b968..00000000 --- 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 1f70fbfa..00000000 --- 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 0c783446..00000000 --- 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 d7c659a9..00000000 --- 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 c87f2ca9..00000000 --- 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 1537da53..00000000 --- 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 ad642ef7..00000000 --- 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 4ac7b82f..00000000 --- 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 87bf870a..00000000 --- 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 b80b8456..00000000 --- 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 7352e417..00000000 --- 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 c6e18b5f..00000000 --- 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 6a17d33a..00000000 --- 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 971c5f96..00000000 --- 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 f54dc063..00000000 --- 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 5b8a5a4e..00000000 --- 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 65ead9ae..00000000 --- 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 82bc953b..00000000 --- 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 5669adde..00000000 --- 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 0fe14988..00000000 --- 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 ca26a998..00000000 --- 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 ed2d5002..00000000 --- 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 615fdf0f..00000000 --- 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 219916fc..00000000 --- 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 4049a179..00000000 --- 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 48f61d20..00000000 --- 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 2dcf5215..00000000 --- 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 ba482a19..00000000 --- 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 5541d8d6..00000000 --- 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 55cf2379..00000000 --- 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 b41ab1d8..00000000 --- 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 19d9a56b..00000000 --- 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 8a7e9307..00000000 --- a/src/app/organization/views/organizationVaultCipherEvents.html +++ /dev/null @@ -1,60 +0,0 @@ - - - diff --git a/src/app/reports/reportsBreachController.js b/src/app/reports/reportsBreachController.js deleted file mode 100644 index ddcb86c0..00000000 --- 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 1ccbf4d5..00000000 --- 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 f4dc4732..00000000 --- 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 99a12238..00000000 --- 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 c69ec0ce..00000000 --- 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 97da93c2..00000000 --- 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 852394d8..00000000 --- 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/eventService.js b/src/app/services/eventService.js deleted file mode 100644 index ce804680..00000000 --- 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 d82f9ac4..00000000 --- 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/passwordService.js b/src/app/services/passwordService.js deleted file mode 100644 index 54504f80..00000000 --- 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/servicesModule.js b/src/app/services/servicesModule.js deleted file mode 100644 index 0fbfca98..00000000 --- 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 3c66b8b4..00000000 --- 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/utilsService.js b/src/app/services/utilsService.js deleted file mode 100644 index f787b418..00000000 --- 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 1e83b2eb..00000000 --- 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 33c8cf1d..00000000 --- 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/settingsAddEditEquivalentDomainController.js b/src/app/settings/settingsAddEditEquivalentDomainController.js deleted file mode 100644 index 3611eed5..00000000 --- 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 ceb1709c..00000000 --- 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 b1a50aac..00000000 --- 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 faf498a7..00000000 --- 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 3b5d7fa5..00000000 --- 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 04cc5908..00000000 --- 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 247a99fa..00000000 --- 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 f31cc37d..00000000 --- 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 9f5bbf4a..00000000 --- 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 f5d1e303..00000000 --- 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 cd193b40..00000000 --- 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 4c5aa7f7..00000000 --- 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 ca9cd7f3..00000000 --- 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 74859d78..00000000 --- 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 9f726a50..00000000 --- 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 18fcdf04..00000000 --- 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 58cd2efc..00000000 --- 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 ad1b14fd..00000000 --- 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 42133f7a..00000000 --- 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 4c2b4dd8..00000000 --- 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 c92cf284..00000000 --- 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 7adfe282..00000000 --- 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 51114604..00000000 --- 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/views/settings.html b/src/app/settings/views/settings.html deleted file mode 100644 index 1b50ffb5..00000000 --- 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 b2fcfbcb..00000000 --- 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 5c67d69b..00000000 --- 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 2d2315cf..00000000 --- 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 5e08b09d..00000000 --- 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 d26834d2..00000000 --- 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 05c359d2..00000000 --- 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 0909fedc..00000000 --- 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 98a9dd8e..00000000 --- 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 aac207e9..00000000 --- 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 9bfe501c..00000000 --- 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 95a210e7..00000000 --- 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 b73d7738..00000000 --- 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 5f612a36..00000000 --- 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 799f6571..00000000 --- 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 29d8f0e4..00000000 --- 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 b93cbcd0..00000000 --- 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 82331652..00000000 --- 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 82b6a84d..00000000 --- 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 1a2e3cff..00000000 --- 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 d9e92004..00000000 --- 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 d72523f0..00000000 --- a/src/app/settings/views/settingsUpdateKey.html +++ /dev/null @@ -1,47 +0,0 @@ - -
- - -
diff --git a/src/app/tools/toolsController.js b/src/app/tools/toolsController.js deleted file mode 100644 index fba3fe88..00000000 --- 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 5d6aa0bd..00000000 --- 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 39f53523..00000000 --- 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 98191f49..00000000 --- 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 242994eb..00000000 --- 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 2a2ecf05..00000000 --- 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 b0d28d74..00000000 --- a/src/app/tools/views/toolsImport.html +++ /dev/null @@ -1,48 +0,0 @@ - -
- - -
- diff --git a/src/app/vault/vaultAddCipherController.js b/src/app/vault/vaultAddCipherController.js deleted file mode 100644 index d35bf5b0..00000000 --- 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 536407a4..00000000 --- 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 7556ad37..00000000 --- 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 9af1d0d7..00000000 --- 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 f4bf780f..00000000 --- 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 635cdadd..00000000 --- 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 438bfe43..00000000 --- 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 84125898..00000000 --- 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 a4f13c3e..00000000 --- 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 bb959e0e..00000000 --- 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 49b8e90a..00000000 --- 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 13ed776d..00000000 --- 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 91a18133..00000000 --- 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 75f9f123..00000000 --- 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 6f72f89b..00000000 --- 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 4f0d0e01..00000000 --- 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 be6d34eb..00000000 --- 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 afef7db6..00000000 --- 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 99938443..00000000 --- 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 cd076260..00000000 --- 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 47e1b0a2..00000000 --- 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 934495ee..00000000 --- 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 1452976a..00000000 --- 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 38939f06..00000000 --- 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 0f7d1dc3..00000000 --- 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/images/boxed-bg-2x.png b/src/images/boxed-bg-2x.png deleted file mode 100644 index 2050e8aa..00000000 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 da898fc3..00000000 Binary files a/src/images/boxed-bg.png and /dev/null differ diff --git a/src/js/analytics.js b/src/js/analytics.js deleted file mode 100644 index 3cab7e7a..00000000 --- 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/fallback-scripts.js b/src/js/fallback-scripts.js deleted file mode 100644 index 76f50c13..00000000 --- a/src/js/fallback-scripts.js +++ /dev/null @@ -1,9 +0,0 @@ -function loadScriptIfMissing(condition, path) { - if (!condition) { - document.write('