mirror of
https://github.com/bitwarden/web
synced 2025-12-06 00:03:28 +00:00
2 lines
37 KiB
JavaScript
2 lines
37 KiB
JavaScript
angular.module("bit",["ui.router","ngMessages","angular-jwt","angular-md5","ui.bootstrap.showErrors","toastr","angulartics","angulartics.google.analytics","bit.directives","bit.services","bit.global","bit.accounts","bit.vault","bit.settings","bit.tools"]),angular.module("bit").constant("appSettings",{rememberedEmailCookieName:"bit.rememberedEmail",version:"1.0.0",environment:"Production",apiUri:"https://api.bitwarden.com"}),angular.module("bit.accounts",["ui.bootstrap","ngCookies"]),angular.module("bit.directives",[]),angular.module("bit.global",[]),angular.module("bit.services",["ngResource","ngStorage","angular-jwt"]),angular.module("bit.settings",["ui.bootstrap","toastr"]),angular.module("bit.tools",["ui.bootstrap","toastr"]),angular.module("bit.vault",["ui.bootstrap","ngclipboard"]),angular.module("bit").factory("apiInterceptor",["$injector","$q","toastr",function(e,t,r){return{request:function(e){return e},response:function(o){return 401!==o.status&&403!==o.status||(e.get("authService").logOut(),e.get("$state").go("frontend.login.info").then(function(){r.warning("Your login session has expired.","Logged out")})),o||t.when(o)},responseError:function(o){return 401!==o.status&&403!==o.status||(e.get("authService").logOut(),e.get("$state").go("frontend.login.info").then(function(){r.warning("Your login session has expired.","Logged out")})),t.reject(o)}}}]),angular.module("bit").config(["$stateProvider","$urlRouterProvider","$httpProvider","jwtInterceptorProvider","$uibTooltipProvider","toastrConfig",function(e,t,r,o,a,n){o.urlParam="access_token",o.tokenGetter=["config","appSettings","tokenService",function(e,t,r){return 0===e.url.indexOf(t.apiUri)?r.getToken():void 0}],angular.extend(n,{closeButton:!0,progressBar:!0,showMethod:"slideDown",target:".toast-target"}),a.options({popupDelay:600}),r.defaults.headers.post&&(r.defaults.headers.post={}),r.defaults.headers.post["Content-Type"]="text/plain; charset=utf-8",r.interceptors.push("apiInterceptor"),r.interceptors.push("jwtInterceptor"),t.otherwise("/"),e.state("backend",{templateUrl:"app/views/backendLayout.html","abstract":!0,data:{authorize:!0}}).state("backend.vault",{url:"^/",templateUrl:"app/vault/views/vault.html",controller:"vaultController",data:{pageTitle:"My Vault"}}).state("backend.settings",{url:"^/settings",templateUrl:"app/settings/views/settings.html",controller:"settingsController",data:{pageTitle:"Settings"}}).state("backend.tools",{url:"^/tools",templateUrl:"app/tools/views/tools.html",controller:"toolsController",data:{pageTitle:"Tools"}}).state("frontend",{templateUrl:"app/views/frontendLayout.html","abstract":!0,data:{authorize:!1}}).state("frontend.login",{templateUrl:"app/accounts/views/accountsLogin.html",controller:"accountsLoginController",data:{bodyClass:"login-page"}}).state("frontend.login.info",{url:"^/login",templateUrl:"app/accounts/views/accountsLoginInfo.html",data:{pageTitle:"Log In"}}).state("frontend.login.twoFactor",{url:"^/login/two-factor",templateUrl:"app/accounts/views/accountsLoginTwoFactor.html",data:{pageTitle:"Log In (Two Factor)",authorizeTwoFactor:!0}}).state("frontend.logout",{url:"^/logout",controller:"accountsLogoutController",data:{authorize:!0}}).state("frontend.passwordHint",{url:"^/password-hint",templateUrl:"app/accounts/views/accountsPasswordHint.html",controller:"accountsPasswordHintController",data:{pageTitle:"Master Password Hint",bodyClass:"login-page"}}).state("frontend.register",{url:"^/register",templateUrl:"app/accounts/views/accountsRegister.html",controller:"accountsRegisterController",data:{pageTitle:"Register",bodyClass:"register-page"}})}]).run(["$rootScope","authService","jwtHelper","tokenService","$state",function(e,t,r,o,a){e.$on("$stateChangeStart",function(e,n,s){return n.data&&n.data.authorize?void(t.isAuthenticated()&&!r.isTokenExpired(o.getToken())||(e.preventDefault(),t.logOut(),a.go("frontend.login.info"))):void(t.isAuthenticated()&&!r.isTokenExpired(o.getToken())&&(e.preventDefault(),a.go("backend.vault")))})}]),angular.module("bit.accounts").controller("accountsLoginController",["$scope","$rootScope","$cookies","apiService","cryptoService","authService","$state","appSettings","$analytics",function(e,t,r,o,a,n,s,i,l){var c=r.get(i.rememberedEmailCookieName);c&&(e.model={email:c,rememberEmail:!0}),e.login=function(t){e.loginPromise=n.logIn(t.email,t.masterPassword),e.loginPromise.then(function(){if(t.rememberEmail){var e=new Date;e.setFullYear(e.getFullYear()+10),r.put(i.rememberedEmailCookieName,t.email,{expires:e})}else r.remove(i.rememberedEmailCookieName);var o=n.getUserProfile();o.twoFactor?(l.eventTrack("Logged In To Two-step"),s.go("frontend.login.twoFactor")):(l.eventTrack("Logged In"),s.go("backend.vault"))})},e.twoFactor=function(t){e.twoFactorPromise=n.logInTwoFactor(t.code,"Authenticator"),e.twoFactorPromise.then(function(){l.eventTrack("Logged In From Two-step"),s.go("backend.vault")})}}]),angular.module("bit.accounts").controller("accountsLogoutController",["$scope","authService","$state","$analytics",function(e,t,r,o){t.logOut(),o.eventTrack("Logged Out"),r.go("frontend.login.info")}]),angular.module("bit.accounts").controller("accountsPasswordHintController",["$scope","$rootScope","apiService",function(e,t,r){e.success=!1,e.submit=function(t){e.submitPromise=r.accounts.postPasswordHint({email:t.email},function(){e.success=!0}).$promise}}]),angular.module("bit.accounts").controller("accountsRegisterController",["$scope","$location","apiService","cryptoService","validationService","$analytics",function(e,t,r,o,a,n){var s=t.search();e.success=!1,e.model={email:s.email},e.registerPromise=null,e.register=function(t){var s=!1;if((e.model.masterPassword.length<8||!/[a-z]/i.test(e.model.masterPassword)||/^[a-zA-Z]*$/.test(e.model.masterPassword))&&(a.addError(t,"MasterPassword","Master password must be at least 8 characters long and contain at least 1 letter and 1 number or special character.",!0),s=!0),e.model.masterPassword!==e.model.confirmMasterPassword&&(a.addError(t,"ConfirmMasterPassword","Master password confirmation does not match.",!0),s=!0),!s){var i=o.makeKey(e.model.masterPassword,e.model.email),l={name:e.model.name,email:e.model.email,masterPasswordHash:o.hashPassword(e.model.masterPassword,i),masterPasswordHint:e.model.masterPasswordHint};e.registerPromise=r.accounts.register(l,function(){e.success=!0,n.eventTrack("Registered")}).$promise}}}]),angular.module("bit.directives").directive("apiField",function(){var e=function(e,t,r,o){function a(){return o.$setValidity("api",!0),!0}function n(){o.$setValidity("api",!1)}o.$registerApiError=n,o.$validators.apiValidate=a};return{require:"ngModel",restrict:"A",compile:function(t,r){if(!r.name||""===r.name)throw"api-field element does not have a valid name attribute";return e}}}),angular.module("bit.directives").directive("apiForm",["$rootScope","validationService",function(e,t){function r(e,r,o){o&&o.then&&(e.$errors=null,e.$loading=!0,o.then(function(t){e.$loading=!1},function(o){e.$loading=!1,t.addErrors(e,o),r.$broadcast("show-errors-check-validity")}))}return{require:"form",restrict:"A",link:function(e,t,o,a){var n=o.apiForm||null;void 0!==n&&e.$watch(n,r.bind(null,a,e))}}}]),angular.module("bit.directives").directive("masterPassword",["cryptoService","authService",function(e,t){return{require:"ngModel",restrict:"A",link:function(r,o,a,n){var s=t.getUserProfile();s&&(n.$parsers.unshift(function(t){if(t){var r=e.makeKey(t,s.email,!0),o=r===e.getKey(!0);return n.$setValidity("masterPassword",o),o?t:void 0}}),n.$formatters.unshift(function(t){if(t){var r=e.makeKey(t,s.email,!0),o=r===e.getKey(!0);return n.$setValidity("masterPassword",o),t}}))}}}]),angular.module("bit.directives").directive("pageTitle",["$rootScope","$timeout","appSettings",function(e,t,r){return{link:function(r,o){var a=function(e,r,a,n,s){var i="bitwarden Password Manager";r.data&&r.data.pageTitle&&(i=r.data.pageTitle+" - bitwarden Password Manager"),t(function(){o.text(i)})};e.$on("$stateChangeStart",a)}}}]),angular.module("bit.directives").directive("passwordMeter",function(){return{template:'<div class="progress {{outerClass}}"><div class="progress-bar progress-bar-{{valueClass}}" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="100" ng-style="{width : ( value + \'%\' ) }"><span class="sr-only">{{value}}%</span></div></div>',restrict:"A",scope:{password:"=passwordMeter",username:"=passwordMeterUsername",outerClass:"@?"},link:function(e){var t=function(e,t){if(!t||t===e)return 0;var r=t.length;return e&&""!==e&&(-1!==e.indexOf(t)&&(r-=15),-1!==t.indexOf(e)&&(r-=e.length)),t.length>0&&t.length<=4?r+=t.length:t.length>=5&&t.length<=7?r+=6:t.length>=8&&t.length<=15?r+=12:t.length>=16&&(r+=18),t.match(/[a-z]/)&&(r+=1),t.match(/[A-Z]/)&&(r+=5),t.match(/\d/)&&(r+=5),t.match(/.*\d.*\d.*\d/)&&(r+=5),t.match(/[!,@,#,$,%,^,&,*,?,_,~]/)&&(r+=5),t.match(/.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~]/)&&(r+=5),t.match(/(?=.*[a-z])(?=.*[A-Z])/)&&(r+=2),t.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/)&&(r+=2),t.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!,@,#,$,%,^,&,*,?,_,~])/)&&(r+=2),r=Math.round(2*r),Math.max(0,Math.min(100,r))},r=function(e){switch(Math.round(e/33)){case 0:case 1:return"danger";case 2:return"warning";case 3:return"success"}},o=function(e){e.value=t(e.username,e.password),e.valueClass=r(e.value)};e.$watch("password",function(){o(e)}),e.$watch("username",function(){o(e)})}}}),angular.module("bit.directives").directive("passwordViewer",function(){return{restrict:"A",link:function(e,t,r){var o=r.passwordViewer;o&&(t.onclick=function(e){},t.on("click",function(e){var r=$(o);r&&"password"===r.attr("type")?(t.removeClass("fa-eye").addClass("fa-eye-slash"),r.attr("type","text")):r&&"text"===r.attr("type")&&(t.removeClass("fa-eye-slash").addClass("fa-eye"),r.attr("type","password"))}))}}}),angular.module("bit.global").controller("mainController",["$scope","$state","authService","appSettings","toastr",function(e,t,r,o,a){var n=this;n.bodyClass="",n.userProfile=null,n.searchVaultText=null,n.version=o.version,e.currentYear=(new Date).getFullYear(),e.$on("$viewContentLoaded",function(){$.AdminLTE&&($.AdminLTE.layout&&($.AdminLTE.layout.fix(),$.AdminLTE.layout.fixSidebar()),$.AdminLTE.pushMenu&&$.AdminLTE.pushMenu.expandOnHover())}),e.$on("$stateChangeSuccess",function(e,t,o,a,s){return n.searchVaultText=null,n.userProfile=r.getUserProfile(),t.data.bodyClass?void(n.bodyClass=t.data.bodyClass):void(n.bodyClass="")}),e.searchVault=function(){t.go("backend.vault")},e.addSite=function(){e.$broadcast("vaultAddSite")},e.addFolder=function(){e.$broadcast("vaultAddFolder")},e.changeEmail=function(){e.$broadcast("settingsChangeEmail")},e.changePassword=function(){e.$broadcast("settingsChangePassword")},e.sessions=function(){e.$broadcast("settingsSessions")},e["delete"]=function(){e.$broadcast("settingsDelete")},e.twoFactor=function(){e.$broadcast("settingsTwoFactor")},e["import"]=function(){e.$broadcast("toolsImport")},e["export"]=function(){e.$broadcast("toolsExport")},e.audits=function(){e.$broadcast("toolsAudits")}}]),angular.module("bit.global").controller("sideNavController",["$scope","$state",function(e,t){e.$state=t}]),angular.module("bit.global").controller("topNavController",["$scope",function(e){}]),angular.module("bit.services").factory("apiService",["$resource","tokenService","appSettings",function(e,t,r){var o={},a=r.apiUri;return o.sites=e(a+"/sites/:id",{},{get:{method:"GET",params:{id:"@id"}},list:{method:"GET",params:{}},post:{method:"POST",params:{}},put:{method:"POST",params:{id:"@id"}},del:{url:a+"/sites/:id/delete",method:"POST",params:{id:"@id"}}}),o.folders=e(a+"/folders/:id",{},{get:{method:"GET",params:{id:"@id"}},list:{method:"GET",params:{}},post:{method:"POST",params:{}},put:{method:"POST",params:{id:"@id"}},del:{url:a+"/folders/:id/delete",method:"POST",params:{id:"@id"}}}),o.ciphers=e(a+"/ciphers/:id",{},{get:{method:"GET",params:{id:"@id"}},list:{method:"GET",params:{}},"import":{url:a+"/ciphers/import",method:"POST",params:{}},favorite:{url:a+"/ciphers/:id/favorite",method:"POST",params:{id:"@id"}},del:{url:a+"/ciphers/:id/delete",method:"POST",params:{id:"@id"}}}),o.accounts=e(a+"/accounts",{},{register:{url:a+"/accounts/register",method:"POST",params:{}},emailToken:{url:a+"/accounts/email-token",method:"POST",params:{}},email:{url:a+"/accounts/email",method:"POST",params:{}},putPassword:{url:a+"/accounts/password",method:"POST",params:{}},getProfile:{url:a+"/accounts/profile",method:"GET",params:{}},putProfile:{url:a+"/accounts/profile",method:"POST",params:{}},getTwoFactor:{url:a+"/accounts/two-factor",method:"GET",params:{}},putTwoFactor:{url:a+"/accounts/two-factor",method:"POST",params:{}},postPasswordHint:{url:a+"/accounts/password-hint",method:"POST",params:{}},putSecurityStamp:{url:a+"/accounts/security-stamp",method:"POST",params:{}},"import":{url:a+"/accounts/import",method:"POST",params:{}},postDelete:{url:a+"/accounts/delete",method:"POST",params:{}}}),o.auth=e(a+"/auth",{},{token:{url:a+"/auth/token",method:"POST",params:{}},tokenTwoFactor:{url:a+"/auth/token/two-factor",method:"POST",params:{}}}),o}]),angular.module("bit.services").factory("authService",["cryptoService","apiService","tokenService","$q","jwtHelper",function(e,t,r,o,a){function n(e){i.extended={name:e.Name,twoFactorEnabled:e.TwoFactorEnabled,culture:e.Culture}}var s={},i=null;return s.logIn=function(a,n){var i=e.makeKey(n,a),l={email:a,masterPasswordHash:e.hashPassword(n,i)},c=o.defer();return t.auth.token(l,function(t){t&&t.Token&&(r.setToken(t.Token),e.setKey(i),s.setUserProfile(t.Profile),c.resolve(t))},function(e){c.reject(e)}),c.promise},s.logInTwoFactor=function(e,a){var n={code:e,provider:a},i=o.defer();return t.auth.tokenTwoFactor(n,function(e){e&&e.Token&&(r.setToken(e.Token),s.setUserProfile(e.Profile),i.resolve(e))},function(e){i.reject(e)}),i.promise},s.logOut=function(){r.clearToken(),e.clearKey(),i=null},s.getUserProfile=function(){return i||s.setUserProfile(),i},s.setUserProfile=function(e){var o=r.getToken();if(o){var s=a.decodeToken(o),l="TwoFactor"===s.authmethod;i={id:s.nameid,email:s.email,twoFactor:l},!l&&e?n(e):l||e||t.accounts.getProfile({},n)}},s.isAuthenticated=function(){return null!==s.getUserProfile()&&!s.getUserProfile().twoFactor},s.isTwoFactorAuthenticated=function(){return null!==s.getUserProfile()&&s.getUserProfile().twoFactor},s}]),angular.module("bit.services").factory("cipherService",["cryptoService","apiService",function(e,t){var r={};return r.decryptSites=function(e){if(!e)throw"encryptedSites is undefined or null";for(var t=[],o=0;o<e.length;o++)t.push(r.decryptSite(e[o]));return t},r.decryptSite=function(t){if(!t)throw"encryptedSite is undefined or null";var r={id:t.Id,type:1,folderId:t.FolderId,favorite:t.Favorite,name:e.decrypt(t.Name),uri:e.decrypt(t.Uri),username:t.Username&&""!==t.Username?e.decrypt(t.Username):null,password:e.decrypt(t.Password),notes:t.Notes&&""!==t.Notes?e.decrypt(t.Notes):null};return t.Folder&&(r.folder={name:e.decrypt(t.Folder.Name)}),r},r.decryptFolders=function(e){if(!e)throw"encryptedFolders is undefined or null";for(var t=[],o=0;o<e.length;o++)t.push(r.decryptFolder(e[o]));return t},r.decryptFolder=function(t){if(!t)throw"encryptedFolder is undefined or null";return{id:t.Id,type:0,name:e.decrypt(t.Name)}},r.encryptSites=function(e,t){if(!e)throw"unencryptedSites is undefined or null";for(var o=[],a=0;a<e.length;a++)o.push(r.encryptSite(e[a],t));return o},r.encryptSite=function(t,r){if(!t)throw"unencryptedSite is undefined or null";return{id:t.id,type:1,folderId:""===t.folderId?null:t.folderId,favorite:null!==t.favorite?t.favorite:!1,uri:e.encrypt(t.uri,r),name:e.encrypt(t.name,r),username:t.username&&""!==t.username?e.encrypt(t.username,r):null,password:e.encrypt(t.password,r),notes:t.notes&&""!==t.notes?e.encrypt(t.notes,r):null}},r.encryptFolders=function(e,t){if(!e)throw"unencryptedFolders is undefined or null";for(var o=[],a=0;a<e.length;a++)o.push(r.encryptFolder(e[a],t));return o},r.encryptFolder=function(t,r){if(!t)throw"unencryptedFolder is undefined or null";return{id:t.id,type:0,name:e.encrypt(t.name,r)}},r}]),angular.module("bit.services").factory("cryptoService",["$sessionStorage",function(e){var t,r,o,a={};return sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."](),a.setKey=function(r){t=r,e.key=sjcl.codec.base64.fromBits(r)},a.getKey=function(o){return o&&o===!0&&r?r:!o&&t?t:(e.key&&(t=sjcl.codec.base64.toBits(e.key)),o&&o===!0?r=sjcl.codec.base64.fromBits(t):t)},a.clearKey=function(){t=r=o=null,delete e.key},a.makeKey=function(e,t,r){var o=sjcl.misc.pbkdf2(e,t,5e3,256,null);return r&&r===!0?sjcl.codec.base64.fromBits(o):o},a.hashPassword=function(e,t){if(t||(t=a.getKey()),!e||!t)throw"Invalid parameters.";var r=sjcl.misc.pbkdf2(t,e,1,256,null);return sjcl.codec.base64.fromBits(r)},a.getAes=function(){return!o&&a.getKey()&&(o=new sjcl.cipher.aes(a.getKey())),o},a.encrypt=function(e,t){if(!a.getKey()&&!t)throw"Encryption key unavailable.";t||(t=a.getKey());var r={},o={mode:"cbc",iv:sjcl.random.randomWords(4,0)},n=sjcl.encrypt(t,e,o,r),s=n.match(/"ct":"([^"]*)"/)[1],i=sjcl.codec.base64.fromBits(r.iv);return i+"|"+s},a.decrypt=function(e){if(!a.getAes())throw"AES encryption unavailable.";var t=e.split("|");if(2!==t.length)return"";var r=sjcl.codec.base64.toBits(t[0]),o=sjcl.codec.base64.toBits(t[1]),n=sjcl.mode.cbc.decrypt(a.getAes(),o,r,null);return sjcl.codec.utf8String.fromBits(n)},a}]),angular.module("bit.services").factory("importService",function(){function e(e,t,r){Papa.parse(e,{header:!0,complete:function(e){var r=[],o=[],a=[];angular.forEach(e.data,function(e,t){if(e.uri&&""!==e.uri){var n=r.length,s=o.length,i=e.folder&&""!==e.folder,l=i;if(i)for(var c=0;c<r.length;c++)if(r[c].name==e.folder){l=!1,n=c;break}if(o.push({favorite:null!==e.favorite?e.favorite:!1,uri:e.uri,username:e.username&&""!==e.username?e.username:null,password:e.password,notes:e.notes&&""!==e.notes?e.notes:null,name:e.name}),l&&r.push({name:e.folder}),i){var u={key:s,value:n};a.push(u)}}}),t(r,o,a)}})}function t(e,t,r){Papa.parse(e,{header:!0,complete:function(e){var r=[],o=[],a=[];angular.forEach(e.data,function(e,t){if(e.url&&""!==e.url){var n=r.length,s=o.length,i=e.grouping&&""!==e.grouping&&"(none)"!=e.grouping,l=i;if(i)for(var c=0;c<r.length;c++)if(r[c].name==e.grouping){l=!1,n=c;break}if(o.push({favorite:"1"==e.fav,uri:e.url,username:e.username&&""!==e.username?e.username:null,password:e.password,notes:e.extra&&""!==e.extra?e.extra:null,name:e.name}),l&&r.push({name:e.grouping}),i){var u={key:s,value:n};a.push(u)}}}),t(r,o,a)}})}var r={};return r["import"]=function(r,o,a,n){switch(r){case"local":e(o,a,n);break;case"lastpass":t(o,a,n);break;default:n()}},r}),angular.module("bit.services").factory("passwordService",function(){function e(e,t){return Math.floor(Math.random()*(t-e+1))+e}var t={};return t.generatePassword=function(t){var r={length:10,ambiguous:!1,number:!0,minNumber:1,uppercase:!0,minUppercase:1,lowercase:!0,minLowercase:1,special:!1,minSpecial:1},o=angular.extend({},r,t);o.uppercase&&o.minUppercase<0&&(o.minUppercase=1),o.lowercase&&o.minLowercase<0&&(o.minLowercase=1),o.number&&o.minNumber<0&&(o.minNumber=1),o.special&&o.minSpecial<0&&(o.minSpecial=1),(!o.length||o.length<1)&&(o.length=10);var a=o.minUppercase+o.minLowercase+o.minNumber+o.minSpecial;o.length<a&&(o.length=a);var n=[];if(o.lowercase&&o.minLowercase>0)for(var s=0;s<o.minLowercase;s++)n.push("l");if(o.uppercase&&o.minUppercase>0)for(var i=0;i<o.minUppercase;i++)n.push("u");if(o.number&&o.minNumber>0)for(var l=0;l<o.minNumber;l++)n.push("n");if(o.special&&o.minSpecial>0)for(var c=0;c<o.minSpecial;c++)n.push("s");for(;n.length<o.length;)n.push("a");n.sort(function(){return 2*e(0,1)-1});var u="",d="abcdefghijkmnopqrstuvwxyz";o.ambiguous&&(d+="l"),o.lowercase&&(u+=d);var p="ABCDEFGHIJKLMNPQRSTUVWXYZ";o.ambiguous&&(p+="O"),o.uppercase&&(u+=p);var m="23456789";o.ambiguous&&(m+="01"),o.number&&(u+=m);var f="!@#$%^&*";o.special&&(u+=f);for(var g="",v=0;v<o.length;v++){var h;switch(n[v]){case"l":h=d;break;case"u":h=p;break;case"n":h=m;break;case"s":h=f;break;case"a":h=u}var w=e(0,h.length-1);g+=h.charAt(w)}return g},t}),angular.module("bit.services").factory("tokenService",["$sessionStorage",function(e){var t,r={};return r.setToken=function(r){e.authBearer=r,t=r},r.getToken=function(){return t||(t=e.authBearer),t},r.clearToken=function(){t=null,delete e.authBearer},r}]),angular.module("bit.services").factory("validationService",function(){var e={};return e.addErrors=function(t,r){var o=r.data,a="An unexpected error has occured.";if(t.$errors=[],!o||!angular.isObject(o))return void t.$errors.push(a);if(!o.ValidationErrors)return void(o.Message?t.$errors.push(o.Message):t.$errors.push(a));for(var n in o.ValidationErrors)if(o.ValidationErrors.hasOwnProperty(n))for(var s=0;s<o.ValidationErrors[n].length;s++)e.addError(t,n,o.ValidationErrors[n][s])},e.addError=function(e,t,r,o){!o&&e.$errors||(e.$errors=[]);for(var a=!0,n=0;n<e.$errors.length;n++)if(e.$errors[n]===r){a=!1;break}a&&e.$errors.push(r),t&&""!==t&&e[t]&&e[t].$registerApiError&&e[t].$registerApiError()},e}),angular.module("bit.settings").controller("settingsChangeEmailController",["$scope","$state","apiService","$uibModalInstance","cryptoService","cipherService","authService","$q","toastr","$analytics",function(e,t,r,o,a,n,s,i,l,c){c.eventTrack("settingsChangeEmailController",{category:"Modal"});var u,d,p;e.token=function(t){u=a.hashPassword(t.masterPassword);var o={newEmail:t.newEmail,masterPasswordHash:u};e.tokenPromise=r.accounts.emailToken(o,function(){p=a.makeKey(t.masterPassword,t.newEmail),d=a.hashPassword(t.masterPassword,p),e.tokenSent=!0}).$promise},e.confirm=function(a){e.processing=!0;var m=[],f=r.sites.list({dirty:!1},function(e){var t=n.decryptSites(e.Data);m=n.encryptSites(t,p)}).$promise,g=[],v=r.folders.list({dirty:!1},function(e){var t=n.decryptFolders(e.Data);g=n.encryptFolders(t,p)}).$promise;i.all([f,v]).then(function(){var n={token:a.token,newEmail:a.newEmail,masterPasswordHash:u,newMasterPasswordHash:d,ciphers:m.concat(g)};e.confirmPromise=r.accounts.email(n,function(){o.dismiss("cancel"),c.eventTrack("Changed Email"),s.logOut(),t.go("frontend.login.info").then(function(){l.success("Please log back in.","Email Changed")})},function(){o.dismiss("cancel"),l.error("Something went wrong.","Oh No!")}).$promise})},e.close=function(){o.dismiss("cancel")}}]),angular.module("bit.settings").controller("settingsChangePasswordController",["$scope","$state","apiService","$uibModalInstance","cryptoService","authService","cipherService","validationService","$q","toastr","$analytics",function(e,t,r,o,a,n,s,i,l,c,u){u.eventTrack("settingsChangePasswordController",{category:"Modal"}),e.save=function(d,p){var m=!1;if((e.model.newMasterPassword.length<8||!/[a-z]/i.test(e.model.newMasterPassword)||/^[a-zA-Z]*$/.test(e.model.newMasterPassword))&&(i.addError(p,"NewMasterPasswordHash","Master password must be at least 8 characters long and contain at least 1 letter and 1 number or special character.",!0),m=!0),e.model.newMasterPassword!==e.model.confirmNewMasterPassword&&(i.addError(p,"ConfirmNewMasterPasswordHash","New master password confirmation does not match.",!0),m=!0),!m){e.processing=!0;var f=n.getUserProfile(),g=a.makeKey(d.newMasterPassword,f.email),v=[],h=r.sites.list({dirty:!1},function(e){var t=s.decryptSites(e.Data);v=s.encryptSites(t,g)}).$promise,w=[],y=r.folders.list({dirty:!1},function(e){var t=s.decryptFolders(e.Data);w=s.encryptFolders(t,g)}).$promise;l.all([h,y]).then(function(){var s={masterPasswordHash:a.hashPassword(d.masterPassword),newMasterPasswordHash:a.hashPassword(d.newMasterPassword,g),ciphers:v.concat(w)};e.savePromise=r.accounts.putPassword(s,function(){o.dismiss("cancel"),n.logOut(),u.eventTrack("Changed Password"),t.go("frontend.login.info").then(function(){c.success("Please log back in.","Master Password Changed")})},function(){o.dismiss("cancel"),c.error("Something went wrong.","Oh No!")}).$promise})}},e.close=function(){o.dismiss("cancel")}}]),angular.module("bit.settings").controller("settingsController",["$scope","$uibModal","apiService","toastr","authService",function(e,t,r,o,a){e.model={},r.accounts.getProfile({},function(t){e.model={name:t.Name,email:t.Email,masterPasswordHint:t.MasterPasswordHint,culture:t.Culture,twoFactorEnabled:t.TwoFactorEnabled}}),e.save=function(t){e.savePromise=r.accounts.putProfile({},t,function(e){a.setUserProfile(e),o.success("Account has been updated.","Success!")}).$promise},e.changePassword=function(){t.open({animation:!0,templateUrl:"app/settings/views/settingsChangePassword.html",controller:"settingsChangePasswordController"})},e.$on("settingsChangePassword",function(t,r){e.changePassword()}),e.changeEmail=function(){t.open({animation:!0,templateUrl:"app/settings/views/settingsChangeEmail.html",controller:"settingsChangeEmailController",size:"sm"})},e.$on("settingsChangeEmail",function(t,r){e.changeEmail()}),e.twoFactor=function(){t.open({animation:!0,templateUrl:"app/settings/views/settingsTwoFactor.html",controller:"settingsTwoFactorController"})},e.$on("settingsTwoFactor",function(t,r){e.twoFactor()}),e.sessions=function(){t.open({animation:!0,templateUrl:"app/settings/views/settingsSessions.html",controller:"settingsSessionsController"})},e.$on("settingsSessions",function(t,r){e.sessions()}),e["delete"]=function(){t.open({animation:!0,templateUrl:"app/settings/views/settingsDelete.html",controller:"settingsDeleteController",size:"sm"})},e.$on("settingsDelete",function(t,r){e["delete"]()})}]),angular.module("bit.settings").controller("settingsDeleteController",["$scope","$state","apiService","$uibModalInstance","cryptoService","authService","toastr","$analytics",function(e,t,r,o,a,n,s,i){i.eventTrack("settingsDeleteController",{category:"Modal"}),e.submit=function(l){var c={masterPasswordHash:a.hashPassword(l.masterPassword)};e.submitPromise=r.accounts.postDelete(c,function(){o.dismiss("cancel"),n.logOut(),i.eventTrack("Deleted Account"),t.go("frontend.login.info").then(function(){s.success("Your account has been closed and all associated data has been deleted.","Account Deleted")})}).$promise},e.close=function(){o.dismiss("cancel")}}]),angular.module("bit.settings").controller("settingsSessionsController",["$scope","$state","apiService","$uibModalInstance","cryptoService","authService","toastr","$analytics",function(e,t,r,o,a,n,s,i){i.eventTrack("settingsSessionsController",{category:"Modal"}),e.submit=function(l){var c={masterPasswordHash:a.hashPassword(l.masterPassword)};e.submitPromise=r.accounts.putSecurityStamp(c,function(){o.dismiss("cancel"),n.logOut(),i.eventTrack("Deauthorized Sessions"),t.go("frontend.login.info").then(function(){s.success("Please log back in.","All Sessions Deauthorized")})}).$promise},e.close=function(){o.dismiss("cancel")}}]),angular.module("bit.settings").controller("settingsTwoFactorController",["$scope","apiService","$uibModalInstance","cryptoService","authService","$q","toastr","$analytics",function(e,t,r,o,a,n,s,i){i.eventTrack("settingsTwoFactorController",{category:"Modal"});var l,c="bitwarden",u=a.getUserProfile();e.account=u.email,e.enabled=function(){return u.extended&&u.extended.twoFactorEnabled},e.auth=function(r){l=o.hashPassword(r.masterPassword),e.authPromise=t.accounts.getTwoFactor({masterPasswordHash:l,provider:0},function(t){var r=t.AuthenticatorKey;e.twoFactorModel={enabled:t.TwoFactorEnabled,key:r.replace(/(.{4})/g,"$1 ").trim(),qr:"https://chart.googleapis.com/chart?chs=120x120&chld=L|0&cht=qr&chl=otpauth://totp/"+c+":"+encodeURIComponent(u.email)+"%3Fsecret="+encodeURIComponent(r)+"%26issuer="+c}}).$promise},e.update=function(r){var o=e.twoFactorModel.enabled;if(!o||confirm("Are you sure you want to disable two-step login?")){var a={enabled:!o,token:r?r.token:null,masterPasswordHash:l};e.updatePromise=t.accounts.putTwoFactor({},a,function(t){t.TwoFactorEnabled?(i.eventTrack("Enabled Two-step Login"),s.success("Two-step login has been enabled."),u.extended&&(u.extended.twoFactorEnabled=!0)):(i.eventTrack("Disabled Two-step Login"),s.success("Two-step login has been disabled."),u.extended&&(u.extended.twoFactorEnabled=!1)),e.close()}).$promise}},e.close=function(){r.dismiss("cancel")}}]),angular.module("bit.tools").controller("toolsAuditsController",["$scope","apiService","$uibModalInstance","toastr","$analytics",function(e,t,r,o,a){a.eventTrack("toolsAuditsController",{category:"Modal"}),e.close=function(){r.dismiss("cancel")}}]),angular.module("bit.tools").controller("toolsController",["$scope","$uibModal","apiService","toastr","authService",function(e,t,r,o,a){e["import"]=function(){t.open({animation:!0,templateUrl:"app/tools/views/toolsImport.html",controller:"toolsImportController",size:"sm"})},e.$on("toolsImport",function(t,r){e["import"]()}),e["export"]=function(){t.open({animation:!0,templateUrl:"app/tools/views/toolsExport.html",controller:"toolsExportController",size:"sm"})},e.$on("toolsExport",function(t,r){e["export"]()}),e.audits=function(){t.open({animation:!0,templateUrl:"app/tools/views/toolsAudits.html",controller:"toolsAuditsController"})},e.$on("toolsAudits",function(t,r){e.audits()})}]),angular.module("bit.tools").controller("toolsExportController",["$scope","apiService","authService","$uibModalInstance","cryptoService","cipherService","$q","toastr","$analytics",function(e,t,r,o,a,n,s,i,l){function c(){var e=new Date,t=e.getFullYear()+""+u(e.getMonth()+1,2)+u(e.getDate(),2)+u(e.getHours(),2)+u(e.getMinutes(),2)+u(e.getSeconds(),2);return"bitwarden_export_"+t+".csv"}function u(e,t,r){return r=r||"0",e+="",e.length>=t?e:new Array(t-e.length+1).join(r)+e}l.eventTrack("toolsExportController",{category:"Modal"}),e["export"]=function(r){e.startedExport=!0,t.sites.list({expand:["folder"]},function(t){try{for(var r=n.decryptSites(t.Data),o=[],a=0;a<r.length;a++){var s={name:r[a].name,uri:r[a].uri,username:r[a].username,password:r[a].password,notes:r[a].notes,folder:r[a].folder?r[a].folder.name:null};o.push(s)}var u=Papa.unparse(o),d=new Blob([u]);if(window.navigator.msSaveOrOpenBlob)window.navigator.msSaveBlob(d,c());else{var p=window.document.createElement("a");p.href=window.URL.createObjectURL(d,{type:"text/plain"}),p.download=c(),document.body.appendChild(p),p.click(),document.body.removeChild(p)}l.eventTrack("Exported Data"),i.success("Your data has been exported. Check your browser's downloads folder.","Success!"),e.close()}catch(m){i.error("Something went wrong. Please try again.","Error!"),e.close()}},function(){i.error("Something went wrong. Please try again.","Error!"),e.close()})},e.close=function(){o.dismiss("cancel")}}]),angular.module("bit.tools").controller("toolsImportController",["$scope","$state","apiService","$uibModalInstance","cryptoService","cipherService","toastr","importService","$analytics",function(e,t,r,o,a,n,s,i,l){function c(e,i,c){r.ciphers["import"]({folders:n.encryptFolders(e,a.getKey()),sites:n.encryptSites(i,a.getKey()),folderRelationships:c},function(){o.dismiss("cancel"),t.go("backend.vault").then(function(){l.eventTrack("Imported Data",{label:model.source}),s.success("Data has been successfully imported into your vault.","Import Success")})},u)}function u(){o.dismiss("cancel"),s.error("Something went wrong. Try again.","Oh No!")}l.eventTrack("toolsImportController",{category:"Modal"}),e.model={source:"local"},e["import"]=function(t){e.processing=!0;var r=document.getElementById("file").files[0];i["import"](t.source,r,c,u)},e.close=function(){o.dismiss("cancel")}}]),angular.module("bit.vault").controller("vaultAddFolderController",["$scope","apiService","$uibModalInstance","cryptoService","cipherService","$analytics",function(e,t,r,o,a,n){n.eventTrack("vaultAddFolderController",{category:"Modal"}),e.savePromise=null,e.save=function(o){var s=a.encryptFolder(o);e.savePromise=t.folders.post(s,function(e){
|
|
n.eventTrack("Created Folder");var t=a.decryptFolder(e);r.close(t)}).$promise},e.close=function(){r.dismiss("close")}}]),angular.module("bit.vault").controller("vaultAddSiteController",["$scope","apiService","$uibModalInstance","cryptoService","cipherService","passwordService","folders","selectedFolder","$analytics",function(e,t,r,o,a,n,s,i,l){function c(e){var t=$(e.trigger).parent().prev();"text"===t.attr("type")&&t.select()}l.eventTrack("vaultAddSiteController",{category:"Modal"}),e.folders=s,e.site={folderId:i?i.id:null},e.savePromise=null,e.save=function(o){var n=a.encryptSite(o);e.savePromise=t.sites.post(n,function(e){l.eventTrack("Created Site");var t=a.decryptSite(e);r.close(t)}).$promise},e.generatePassword=function(){e.site.password&&!confirm("Are you sure you want to overwrite the current password?")||(l.eventTrack("Generated Password From Add"),e.site.password=n.generatePassword({length:10,special:!0}))},e.clipboardSuccess=function(e){e.clearSelection(),c(e)},e.clipboardError=function(e,t){t&&c(e),alert("Your web browser does not support easy clipboard copying. Copy it manually instead.")},e.close=function(){r.dismiss("close")}}]),angular.module("bit.vault").controller("vaultController",["$scope","$uibModal","apiService","$filter","cryptoService","authService","toastr","cipherService",function(e,t,r,o,a,n,s,i){e.sites=[],e.folders=[],e.loadingSites=!0,r.sites.list({},function(t){e.loadingSites=!1;for(var r=[],o=0;o<t.Data.length;o++){var n={id:t.Data[o].Id,folderId:t.Data[o].FolderId,favorite:t.Data[o].Favorite};try{n.name=a.decrypt(t.Data[o].Name)}catch(s){n.name="[error: cannot decrypt]"}if(t.Data[o].Username)try{n.username=a.decrypt(t.Data[o].Username)}catch(s){n.username="[error: cannot decrypt]"}r.push(n)}e.sites=r},function(){e.loadingSites=!1}),e.loadingFolders=!0,r.folders.list({},function(t){e.loadingFolders=!1;for(var r=[{id:null,name:"(none)"}],o=0;o<t.Data.length;o++){var n={id:t.Data[o].Id};try{n.name=a.decrypt(t.Data[o].Name)}catch(s){n.name="[error: cannot decrypt]"}r.push(n)}e.folders=r},function(){e.loadingFolders=!1}),e.folderSort=function(e){return e.id?e.name.toLowerCase():""},e.editSite=function(r){var a=t.open({animation:!0,templateUrl:"app/vault/views/vaultEditSite.html",controller:"vaultEditSiteController",resolve:{siteId:function(){return r.id},folders:function(){return e.folders}}});a.result.then(function(t){var r=o("filter")(e.sites,{id:t.id},!0);r&&r.length>0&&(r[0].folderId=t.folderId,r[0].name=t.name,r[0].username=t.username,r[0].favorite=t.favorite)})},e.$on("vaultAddSite",function(t,r){e.addSite()}),e.addSite=function(r){var o=t.open({animation:!0,templateUrl:"app/vault/views/vaultAddSite.html",controller:"vaultAddSiteController",resolve:{folders:function(){return e.folders},selectedFolder:function(){return r}}});o.result.then(function(t){e.sites.push(t)})},e.deleteSite=function(t){confirm("Are you sure you want to delete this site ("+t.name+")?")&&r.sites.del({id:t.id},function(){var r=e.sites.indexOf(t);e.sites.splice(r,1)})},e.editFolder=function(r){var a=t.open({animation:!0,templateUrl:"app/vault/views/vaultEditFolder.html",controller:"vaultEditFolderController",size:"sm",resolve:{folderId:function(){return r.id}}});a.result.then(function(t){var r=o("filter")(e.folders,{id:t.id},!0);r&&r.length>0&&(r[0].name=t.name)})},e.$on("vaultAddFolder",function(t,r){e.addFolder()}),e.addFolder=function(){var r=t.open({animation:!0,templateUrl:"app/vault/views/vaultAddFolder.html",controller:"vaultAddFolderController",size:"sm"});r.result.then(function(t){e.folders.push(t)})},e.deleteFolder=function(t){confirm("Are you sure you want to delete this folder ("+t.name+")?")&&r.folders.del({id:t.id},function(){var r=e.folders.indexOf(t);e.folders.splice(r,1)})},e.canDeleteFolder=function(t){if(!t||!t.id)return!1;var r=o("filter")(e.sites,{folderId:t.id});return 0===r.length}}]),angular.module("bit.vault").controller("vaultEditFolderController",["$scope","apiService","$uibModalInstance","cryptoService","cipherService","folderId","$analytics",function(e,t,r,o,a,n,s){s.eventTrack("vaultEditFolderController",{category:"Modal"}),e.folder={},t.folders.get({id:n},function(t){e.folder=a.decryptFolder(t)}),e.savePromise=null,e.save=function(o){var i=a.encryptFolder(o);e.savePromise=t.folders.put({id:n},i,function(e){s.eventTrack("Edited Folder");var t=a.decryptFolder(e);r.close(t)}).$promise},e.close=function(){r.dismiss("cancel")}}]),angular.module("bit.vault").controller("vaultEditSiteController",["$scope","apiService","$uibModalInstance","cryptoService","cipherService","passwordService","siteId","folders","$analytics",function(e,t,r,o,a,n,s,i,l){function c(e){var t=$(e.trigger).parent().prev();"text"===t.attr("type")&&t.select()}l.eventTrack("vaultEditSiteController",{category:"Modal"}),e.folders=i,e.site={},t.sites.get({id:s},function(t){e.site=a.decryptSite(t)}),e.save=function(o){var n=a.encryptSite(o);e.savePromise=t.sites.put({id:s},n,function(e){l.eventTrack("Edited Site");var t=a.decryptSite(e);r.close(t)}).$promise},e.generatePassword=function(){e.site.password&&!confirm("Are you sure you want to overwrite the current password?")||(l.eventTrack("Generated Password From Edit"),e.site.password=n.generatePassword({length:10,special:!0}))},e.clipboardSuccess=function(e){e.clearSelection(),c(e)},e.clipboardError=function(e,t){t&&c(e),alert("Your web browser does not support easy clipboard copying. Copy it manually instead.")},e.close=function(){r.dismiss("cancel")}}]); |