From e322c777257951bc6782e74a488145c75959950d Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Sat, 3 Sep 2016 00:03:13 -0400 Subject: [PATCH] setup various pages and services --- src/background.js | 4 +- .../app/accounts/accountsLoginController.js | 14 -- src/browser_action/app/config.js | 61 --------- src/manifest.json | 22 ++- .../app/accounts/accountsLoginController.js | 23 ++++ .../app/accounts/accountsModule.js | 0 .../app/accounts/views/accountsLogin.html | 0 .../views/accountsLoginTwoFactor.html | 0 src/{browser_action => popup}/app/app.js | 3 + src/popup/app/config.js | 110 +++++++++++++++ .../app/current/currentController.js | 0 .../app/current/currentModule.js | 0 .../app/current/views/current.html | 0 .../app/global/tabs.html | 0 src/popup/app/services/apiService.js | 53 ++++++++ src/popup/app/services/backgroundService.js | 12 ++ src/popup/app/services/loginService.js | 68 ++++++++++ src/popup/app/services/servicesModule.js | 2 + src/popup/app/settings.js | 2 + .../app/settings/settingsController.js | 0 .../app/settings/settingsModule.js | 0 .../app/settings/views/settings.html | 0 .../app/tools/toolsController.js | 0 .../app/tools/toolsModule.js | 0 .../app/tools/views/tools.html | 0 .../app/vault/vaultController.js | 0 .../app/vault/vaultModule.js | 0 .../app/vault/views/vault.html | 0 src/{browser_action => popup}/index.html | 16 +-- src/services/authService.js | 126 ------------------ src/services/cryptoService.js | 44 +++--- src/services/tokenService.js | 22 +-- src/services/userService.js | 87 ++++++++++++ 33 files changed, 425 insertions(+), 244 deletions(-) delete mode 100644 src/browser_action/app/accounts/accountsLoginController.js delete mode 100644 src/browser_action/app/config.js create mode 100644 src/popup/app/accounts/accountsLoginController.js rename src/{browser_action => popup}/app/accounts/accountsModule.js (100%) rename src/{browser_action => popup}/app/accounts/views/accountsLogin.html (100%) rename src/{browser_action => popup}/app/accounts/views/accountsLoginTwoFactor.html (100%) rename src/{browser_action => popup}/app/app.js (77%) create mode 100644 src/popup/app/config.js rename src/{browser_action => popup}/app/current/currentController.js (100%) rename src/{browser_action => popup}/app/current/currentModule.js (100%) rename src/{browser_action => popup}/app/current/views/current.html (100%) rename src/{browser_action => popup}/app/global/tabs.html (100%) create mode 100644 src/popup/app/services/apiService.js create mode 100644 src/popup/app/services/backgroundService.js create mode 100644 src/popup/app/services/loginService.js create mode 100644 src/popup/app/services/servicesModule.js create mode 100644 src/popup/app/settings.js rename src/{browser_action => popup}/app/settings/settingsController.js (100%) rename src/{browser_action => popup}/app/settings/settingsModule.js (100%) rename src/{browser_action => popup}/app/settings/views/settings.html (100%) rename src/{browser_action => popup}/app/tools/toolsController.js (100%) rename src/{browser_action => popup}/app/tools/toolsModule.js (100%) rename src/{browser_action => popup}/app/tools/views/tools.html (100%) rename src/{browser_action => popup}/app/vault/vaultController.js (100%) rename src/{browser_action => popup}/app/vault/vaultModule.js (100%) rename src/{browser_action => popup}/app/vault/views/vault.html (100%) rename src/{browser_action => popup}/index.html (74%) delete mode 100644 src/services/authService.js create mode 100644 src/services/userService.js diff --git a/src/background.js b/src/background.js index 5f282702bb..077ada5ca4 100644 --- a/src/background.js +++ b/src/background.js @@ -1 +1,3 @@ - \ No newline at end of file +var cryptoService = new CryptoService(); +var tokenService = new TokenService(); +var userService = new UserService(tokenService); diff --git a/src/browser_action/app/accounts/accountsLoginController.js b/src/browser_action/app/accounts/accountsLoginController.js deleted file mode 100644 index a3ba091a9a..0000000000 --- a/src/browser_action/app/accounts/accountsLoginController.js +++ /dev/null @@ -1,14 +0,0 @@ -angular - .module('bit.accounts') - - .controller('accountsLoginController', function ($scope, $state) { - $scope.login = function (model) { - g_authService.logIn(model.email, model.masterPassword, function () { - $state.go('tabs.current'); - }); - }; - - $scope.twoFactor = function (model) { - $state.go('tabs.current'); - }; - }); diff --git a/src/browser_action/app/config.js b/src/browser_action/app/config.js deleted file mode 100644 index 3fd194ba2d..0000000000 --- a/src/browser_action/app/config.js +++ /dev/null @@ -1,61 +0,0 @@ -angular - .module('bit') - - .config(function ($stateProvider, $urlRouterProvider) { - - $stateProvider - .state('login', { - url: "/login", - controller: 'accountsLoginController', - templateUrl: "app/accounts/views/accountsLogin.html" - }) - .state('login.twoFactor', { - url: "/two-factor", - controller: 'accountsLoginController', - templateUrl: "app/accounts/views/accountsLoginTwoFactor.html" - }) - .state('tabs', { - url: "/tab", - abstract: true, - templateUrl: "app/global/tabs.html" - }) - .state('tabs.current', { - url: "/current", - views: { - 'current-tab': { - templateUrl: "app/current/views/current.html", - controller: 'currentController' - } - } - }) - .state('tabs.vault', { - url: "/vault", - views: { - 'vault-tab': { - templateUrl: "app/vault/views/vault.html", - controller: 'vaultController' - } - } - }) - .state('tabs.settings', { - url: "/settings", - views: { - 'settings-tab': { - templateUrl: "app/settings/views/settings.html", - controller: 'settingsController' - } - } - }) - .state('tabs.tools', { - url: "/tools", - views: { - 'tools-tab': { - templateUrl: "app/tools/views/tools.html", - controller: 'toolsController' - } - } - }); - - - $urlRouterProvider.otherwise("/login"); - }); diff --git a/src/manifest.json b/src/manifest.json index a5f5c3b537..2e50e396c0 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -12,7 +12,15 @@ "128": "images/icon128.png" }, "background": { - "scripts": [ "background.js" ] + "scripts": [ + "node_modules/sjcl/sjcl.js", + "node_modules/sjcl/core/cbc.js", + "node_modules/sjcl/core/bitArray.js", + "services/cryptoService.js", + "services/tokenService.js", + "services/userService.js", + "background.js" + ] }, "browser_action": { "default_icon": { @@ -20,10 +28,18 @@ "38": "images/icon38.png" }, "default_title": "bitwarden", - "default_popup": "browser_action/index.html" + "default_popup": "popup/index.html" }, "permissions": [ + "tabs", + "idle", + "notifications", + "contextMenus", "storage", - "unlimitedStorage" + "unlimitedStorage", + "webRequest", + "webRequestBlocking", + "http://*/*", + "https://*/*" ] } \ No newline at end of file diff --git a/src/popup/app/accounts/accountsLoginController.js b/src/popup/app/accounts/accountsLoginController.js new file mode 100644 index 0000000000..1768c33006 --- /dev/null +++ b/src/popup/app/accounts/accountsLoginController.js @@ -0,0 +1,23 @@ +angular + .module('bit.accounts') + + .controller('accountsLoginController', function ($scope, $state, loginService, userService) { + $scope.login = function (model) { + $scope.loginPromise = loginService.logIn(model.email, model.masterPassword); + + $scope.loginPromise.then(function () { + userService.getUserProfile(function (profile) { + if (profile.twoFactor) { + $state.go('login.twoFactor'); + } + else { + $state.go('tabs.current'); + } + }); + }); + }; + + $scope.twoFactor = function (model) { + $state.go('tabs.current'); + }; + }); diff --git a/src/browser_action/app/accounts/accountsModule.js b/src/popup/app/accounts/accountsModule.js similarity index 100% rename from src/browser_action/app/accounts/accountsModule.js rename to src/popup/app/accounts/accountsModule.js diff --git a/src/browser_action/app/accounts/views/accountsLogin.html b/src/popup/app/accounts/views/accountsLogin.html similarity index 100% rename from src/browser_action/app/accounts/views/accountsLogin.html rename to src/popup/app/accounts/views/accountsLogin.html diff --git a/src/browser_action/app/accounts/views/accountsLoginTwoFactor.html b/src/popup/app/accounts/views/accountsLoginTwoFactor.html similarity index 100% rename from src/browser_action/app/accounts/views/accountsLoginTwoFactor.html rename to src/popup/app/accounts/views/accountsLoginTwoFactor.html diff --git a/src/browser_action/app/app.js b/src/popup/app/app.js similarity index 77% rename from src/browser_action/app/app.js rename to src/popup/app/app.js index e6b4c6b980..a907cb90ef 100644 --- a/src/browser_action/app/app.js +++ b/src/popup/app/app.js @@ -1,6 +1,9 @@ angular .module('bit', [ 'ionic', + 'angular-jwt', + + 'bit.services', 'bit.accounts', 'bit.current', diff --git a/src/popup/app/config.js b/src/popup/app/config.js new file mode 100644 index 0000000000..f55de6fa6b --- /dev/null +++ b/src/popup/app/config.js @@ -0,0 +1,110 @@ +angular + .module('bit') + + .config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider) { + jwtInterceptorProvider.urlParam = 'access_token'; + jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (config, appSettings, tokenService) { + if (config.url.indexOf(appSettings.apiUri) === 0) { + tokenService.getToken(function (token) { + return token; + }); + } + }; + + if ($httpProvider.defaults.headers.post) { + $httpProvider.defaults.headers.post = {}; + } + + $httpProvider.defaults.headers.post['Content-Type'] = 'text/plain; charset=utf-8'; + + //$httpProvider.interceptors.push('apiInterceptor'); + $httpProvider.interceptors.push('jwtInterceptor'); + + $urlRouterProvider.otherwise(function ($injector, $location) { + var $state = $injector.get("$state"); + $state.go("login"); + }); + + $stateProvider + .state('login', { + url: "/login", + controller: 'accountsLoginController', + templateUrl: "app/accounts/views/accountsLogin.html", + data: { + authorize: false + } + }) + .state('login.twoFactor', { + url: "/two-factor", + controller: 'accountsLoginController', + templateUrl: "app/accounts/views/accountsLoginTwoFactor.html" + }) + + .state('tabs', { + url: "/tab", + abstract: true, + templateUrl: "app/global/tabs.html", + data: { + authorize: true + } + }) + .state('tabs.current', { + url: "/current", + views: { + 'current-tab': { + templateUrl: "app/current/views/current.html", + controller: 'currentController' + } + } + }) + .state('tabs.vault', { + url: "/vault", + views: { + 'vault-tab': { + templateUrl: "app/vault/views/vault.html", + controller: 'vaultController' + } + } + }) + .state('tabs.settings', { + url: "/settings", + views: { + 'settings-tab': { + templateUrl: "app/settings/views/settings.html", + controller: 'settingsController' + } + } + }) + .state('tabs.tools', { + url: "/tools", + views: { + 'tools-tab': { + templateUrl: "app/tools/views/tools.html", + controller: 'toolsController' + } + } + }); + }) + .run(function ($rootScope, userService, loginService, jwtHelper, tokenService, $state) { + $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { + tokenService.getToken(function (token) { + userService.isAuthenticated(function (isAuthenticated) { + if (!toState.data || !toState.data.authorize) { + if (isAuthenticated && !jwtHelper.isTokenExpired(token)) { + event.preventDefault(); + $state.go('tabs.current'); + } + + return; + } + + if (!isAuthenticated || jwtHelper.isTokenExpired(token)) { + event.preventDefault(); + loginService.logOut(function () { + $state.go('login'); + }); + } + }); + }); + }); + }); diff --git a/src/browser_action/app/current/currentController.js b/src/popup/app/current/currentController.js similarity index 100% rename from src/browser_action/app/current/currentController.js rename to src/popup/app/current/currentController.js diff --git a/src/browser_action/app/current/currentModule.js b/src/popup/app/current/currentModule.js similarity index 100% rename from src/browser_action/app/current/currentModule.js rename to src/popup/app/current/currentModule.js diff --git a/src/browser_action/app/current/views/current.html b/src/popup/app/current/views/current.html similarity index 100% rename from src/browser_action/app/current/views/current.html rename to src/popup/app/current/views/current.html diff --git a/src/browser_action/app/global/tabs.html b/src/popup/app/global/tabs.html similarity index 100% rename from src/browser_action/app/global/tabs.html rename to src/popup/app/global/tabs.html diff --git a/src/popup/app/services/apiService.js b/src/popup/app/services/apiService.js new file mode 100644 index 0000000000..f1a1ef268c --- /dev/null +++ b/src/popup/app/services/apiService.js @@ -0,0 +1,53 @@ +angular + .module('bit.services') + + .factory('apiService', function ($resource, appSettings) { + var _service = {}, + _apiUri = appSettings.apiUri; + + _service.sites = $resource(_apiUri + '/sites/:id', {}, { + get: { method: 'GET', params: { id: '@id' } }, + list: { method: 'GET', params: {} }, + post: { method: 'POST', params: {} }, + put: { method: 'POST', params: { id: '@id' } }, + del: { url: _apiUri + '/sites/:id/delete', method: 'POST', params: { id: '@id' } } + }); + + _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' } }, + list: { method: 'GET', params: {} }, + 'import': { url: _apiUri + '/ciphers/import', method: 'POST', params: {} }, + favorite: { url: _apiUri + '/ciphers/:id/favorite', method: 'POST', params: { id: '@id' } }, + del: { url: _apiUri + '/ciphers/:id/delete', method: 'POST', params: { id: '@id' } } + }); + + _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: {} }, + putPassword: { url: _apiUri + '/accounts/password', method: 'POST', params: {} }, + getProfile: { url: _apiUri + '/accounts/profile', method: 'GET', params: {} }, + putProfile: { url: _apiUri + '/accounts/profile', method: 'POST', params: {} }, + getTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'GET', params: {} }, + putTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'POST', params: {} }, + postPasswordHint: { url: _apiUri + '/accounts/password-hint', method: 'POST', params: {} }, + putSecurityStamp: { url: _apiUri + '/accounts/security-stamp', method: 'POST', params: {} }, + 'import': { url: _apiUri + '/accounts/import', method: 'POST', params: {} }, + postDelete: { url: _apiUri + '/accounts/delete', method: 'POST', params: {} } + }); + + _service.auth = $resource(_apiUri + '/auth', {}, { + token: { url: _apiUri + '/auth/token', method: 'POST', params: {} }, + tokenTwoFactor: { url: _apiUri + '/auth/token/two-factor', method: 'POST', params: {} } + }); + + return _service; + }); diff --git a/src/popup/app/services/backgroundService.js b/src/popup/app/services/backgroundService.js new file mode 100644 index 0000000000..1216809967 --- /dev/null +++ b/src/popup/app/services/backgroundService.js @@ -0,0 +1,12 @@ +angular + .module('bit.services') + + .factory('tokenService', function () { + return chrome.extension.getBackgroundPage().tokenService; + }) + .factory('cryptoService', function () { + return chrome.extension.getBackgroundPage().cryptoService; + }) + .factory('userService', function () { + return chrome.extension.getBackgroundPage().userService; + }); diff --git a/src/popup/app/services/loginService.js b/src/popup/app/services/loginService.js new file mode 100644 index 0000000000..ca9620dce1 --- /dev/null +++ b/src/popup/app/services/loginService.js @@ -0,0 +1,68 @@ +angular + .module('bit.services') + + .factory('loginService', function (cryptoService, apiService, userService, tokenService, $q) { + var _service = {}; + + _service.logIn = function (email, masterPassword) { + var key = cryptoService.makeKey(masterPassword, email); + + var request = { + email: email, + masterPasswordHash: cryptoService.hashPassword(masterPassword, key) + }; + + var deferred = $q.defer(); + apiService.auth.token(request, function (response) { + if (!response || !response.Token) { + return; + } + + tokenService.setToken(response.Token, function () { + cryptoService.setKey(key, function () { + userService.setUserProfile(response.Profile, function () { + deferred.resolve(response); + }); + }); + }); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + }; + + _service.logInTwoFactor = function (code, provider) { + var request = { + code: code, + provider: provider + }; + + var deferred = $q.defer(); + apiService.auth.tokenTwoFactor(request, function (response) { + if (!response || !response.Token) { + return; + } + + tokenService.setToken(response.Token, function () { + userService.setUserProfile(response.Profile, function () { + deferred.resolve(response); + }); + }); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + }; + + _service.logOut = function () { + tokenService.clearToken(function () { + cryptoService.clearKey(function () { + userService.clearUserProfile(); + }); + }); + }; + + return _service; + }); diff --git a/src/popup/app/services/servicesModule.js b/src/popup/app/services/servicesModule.js new file mode 100644 index 0000000000..49effbfd8b --- /dev/null +++ b/src/popup/app/services/servicesModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.services', ['ngResource', 'angular-jwt']); diff --git a/src/popup/app/settings.js b/src/popup/app/settings.js new file mode 100644 index 0000000000..c2fd3310f5 --- /dev/null +++ b/src/popup/app/settings.js @@ -0,0 +1,2 @@ +angular.module("bit") +.constant("appSettings", { "rememberdEmailCookieName": "bit.rememberedEmail", "version": "0.0.1", "environment": "Development", "apiUri": "https://api.bitwarden.com" }); diff --git a/src/browser_action/app/settings/settingsController.js b/src/popup/app/settings/settingsController.js similarity index 100% rename from src/browser_action/app/settings/settingsController.js rename to src/popup/app/settings/settingsController.js diff --git a/src/browser_action/app/settings/settingsModule.js b/src/popup/app/settings/settingsModule.js similarity index 100% rename from src/browser_action/app/settings/settingsModule.js rename to src/popup/app/settings/settingsModule.js diff --git a/src/browser_action/app/settings/views/settings.html b/src/popup/app/settings/views/settings.html similarity index 100% rename from src/browser_action/app/settings/views/settings.html rename to src/popup/app/settings/views/settings.html diff --git a/src/browser_action/app/tools/toolsController.js b/src/popup/app/tools/toolsController.js similarity index 100% rename from src/browser_action/app/tools/toolsController.js rename to src/popup/app/tools/toolsController.js diff --git a/src/browser_action/app/tools/toolsModule.js b/src/popup/app/tools/toolsModule.js similarity index 100% rename from src/browser_action/app/tools/toolsModule.js rename to src/popup/app/tools/toolsModule.js diff --git a/src/browser_action/app/tools/views/tools.html b/src/popup/app/tools/views/tools.html similarity index 100% rename from src/browser_action/app/tools/views/tools.html rename to src/popup/app/tools/views/tools.html diff --git a/src/browser_action/app/vault/vaultController.js b/src/popup/app/vault/vaultController.js similarity index 100% rename from src/browser_action/app/vault/vaultController.js rename to src/popup/app/vault/vaultController.js diff --git a/src/browser_action/app/vault/vaultModule.js b/src/popup/app/vault/vaultModule.js similarity index 100% rename from src/browser_action/app/vault/vaultModule.js rename to src/popup/app/vault/vaultModule.js diff --git a/src/browser_action/app/vault/views/vault.html b/src/popup/app/vault/views/vault.html similarity index 100% rename from src/browser_action/app/vault/views/vault.html rename to src/popup/app/vault/views/vault.html diff --git a/src/browser_action/index.html b/src/popup/index.html similarity index 74% rename from src/browser_action/index.html rename to src/popup/index.html index 4dac44e5b9..5903f60491 100644 --- a/src/browser_action/index.html +++ b/src/popup/index.html @@ -7,18 +7,18 @@ - - - - - - - - + + + + + + + + diff --git a/src/services/authService.js b/src/services/authService.js deleted file mode 100644 index 8f29b9dc1d..0000000000 --- a/src/services/authService.js +++ /dev/null @@ -1,126 +0,0 @@ -var g_authService = function () { - var _service = {}, _userProfile = null; - - _service.logIn = function (email, masterPassword, callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - var key = g_cryptoService.makeKey(masterPassword, email); - - var request = { - email: email, - masterPasswordHash: g_cryptoService.hashPassword(masterPassword, key) - }; - - var response = { - Token: "", - Profile: { - - } - }; - - g_tokenService.setToken(response.Token, function () { - g_cryptoService.setKey(key, function () { - _service.setUserProfile(response.Profile, function () { - callback(); - }); - }); - }); - }; - - _service.logInTwoFactor = function (code, provider, callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - return; - }; - - _service.logOut = function (callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - g_tokenService.clearToken(function () { - g_cryptoService.clearKey(function () { - _userProfile = null; - callback(); - }); - }); - }; - - _service.getUserProfile = function (callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - if (!_userProfile) { - _service.setUserProfile(null, function () { - callback(_userProfile); - }); - } - - return callback(_userProfile); - }; - - _service.setUserProfile = function (profile, callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - g_tokenService.getToken(function (token) { - if (!token) { - return; - } - - var decodedToken = jwtHelper.decodeToken(token); - var twoFactor = decodedToken.authmethod === "TwoFactor"; - - _userProfile = { - id: decodedToken.nameid, - email: decodedToken.email, - twoFactor: twoFactor - }; - - if (!twoFactor && profile) { - loadProfile(profile); - } - else if (!twoFactor && !profile) { - apiService.accounts.getProfile({}, loadProfile); - } - - callback(); - }); - }; - - function loadProfile(profile) { - _userProfile.extended = { - name: profile.Name, - twoFactorEnabled: profile.TwoFactorEnabled, - culture: profile.Culture - }; - } - - _service.isAuthenticated = function (callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - callback(_service.getUserProfile(function (profile) { - return profile !== null && !profile.twoFactor; - })); - }; - - _service.isTwoFactorAuthenticated = function (callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } - - callback(_service.getUserProfile(function (profile) { - return profile !== null && profile.twoFactor; - })); - }; - - return _service; -}(); diff --git a/src/services/cryptoService.js b/src/services/cryptoService.js index 33370a208c..fcf9bb5a0d 100644 --- a/src/services/cryptoService.js +++ b/src/services/cryptoService.js @@ -1,9 +1,13 @@ -var g_cryptoService = function () { - var _service = {}, _key, _b64Key, _aes; +function CryptoService() { - sjcl.beware['CBC mode is dangerous because it doesn\'t protect message integrity.'](); +}; - _service.setKey = function (key, callback) { +!function () { + var _key, + _b64Key, + _aes; + + CryptoService.prototype.setKey = function (key, callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; } @@ -14,9 +18,9 @@ }, function () { callback(); }); - }; + } - _service.getKey = function (b64, callback) { + CryptoService.prototype.getKey = function (b64, callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; } @@ -42,7 +46,7 @@ }); }; - _service.clearKey = function (callback) { + CryptoService.prototype.clearKey = function (callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; } @@ -53,7 +57,7 @@ }); }; - _service.makeKey = function (password, salt, b64) { + CryptoService.prototype.makeKey = function (password, salt, b64) { var key = sjcl.misc.pbkdf2(password, salt, 5000, 256, null); if (b64 && b64 === true) { @@ -63,9 +67,9 @@ return key; }; - _service.hashPassword = function (password, key) { + CryptoService.prototype.hashPassword = function (password, key) { if (!key) { - key = _service.getKey(); + key = this.getKey(); } if (!password || !key) { @@ -76,21 +80,21 @@ return sjcl.codec.base64.fromBits(hashBits); }; - _service.getAes = function () { - if (!_aes && _service.getKey()) { - _aes = new sjcl.cipher.aes(_service.getKey()); + CryptoService.prototype.getAes = function () { + if (!_aes && this.getKey()) { + _aes = new sjcl.cipher.aes(this.getKey()); } return _aes; }; - _service.encrypt = function (plaintextValue, key) { - if (!_service.getKey() && !key) { + CryptoService.prototype.encrypt = function (plaintextValue, key) { + if (!this.getKey() && !key) { throw 'Encryption key unavailable.'; } if (!key) { - key = _service.getKey(); + key = this.getKey(); } var response = {}; @@ -107,8 +111,8 @@ return iv + "|" + ct; }; - _service.decrypt = function (encValue) { - if (!_service.getAes()) { + CryptoService.prototype.decrypt = function (encValue) { + if (!this.getAes()) { throw 'AES encryption unavailable.'; } @@ -120,9 +124,7 @@ var ivBits = sjcl.codec.base64.toBits(encPieces[0]); var ctBits = sjcl.codec.base64.toBits(encPieces[1]); - var decBits = sjcl.mode.cbc.decrypt(_service.getAes(), ctBits, ivBits, null); + var decBits = sjcl.mode.cbc.decrypt(this.getAes(), ctBits, ivBits, null); return sjcl.codec.utf8String.fromBits(decBits); }; - - return _service; }(); diff --git a/src/services/tokenService.js b/src/services/tokenService.js index 2ba7b09b37..597c38c1de 100644 --- a/src/services/tokenService.js +++ b/src/services/tokenService.js @@ -1,7 +1,11 @@ -var g_tokenService = function () { - var _service = {}, _token; +function TokenService() { - _service.setToken = function (token, callback) { +}; + +!function () { + var _token; + + TokenService.prototype.setToken = function (token, callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; } @@ -14,7 +18,7 @@ }); }; - _service.getToken = function (callback) { + TokenService.prototype.getToken = function (callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; } @@ -23,16 +27,16 @@ return callback(_token); } - chrome.storage.local.get('authBearer', function (authBearer) { - if (authBearer) { - _token = authBearer; + chrome.storage.local.get('authBearer', function (obj) { + if (obj && obj.authBearer) { + _token = obj.authBearer; } return callback(_token); }); }; - _service.clearToken = function (callback) { + TokenService.prototype.clearToken = function (callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; } @@ -42,6 +46,4 @@ callback(); }); }; - - return _service; }(); diff --git a/src/services/userService.js b/src/services/userService.js new file mode 100644 index 0000000000..89b765be24 --- /dev/null +++ b/src/services/userService.js @@ -0,0 +1,87 @@ +function UserService(tokenService) { + this.tokenService = tokenService; +}; + +!function () { + var _userProfile = null; + + UserService.prototype.getUserProfile = function (callback) { + if (!callback || typeof callback !== 'function') { + throw 'callback function required'; + } + + if (_userProfile) { + callback(_userProfile); + return; + } + + this.setUserProfile(null, function () { + callback(_userProfile); + }); + }; + + UserService.prototype.setUserProfile = function (profile, callback) { + if (!callback || typeof callback !== 'function') { + throw 'callback function required'; + } + + this.tokenService.getToken(function (token) { + if (!token) { + return; + } + + //var decodedToken = jwtHelper.decodeToken(token); + var twoFactor = false;// decodedToken.authmethod === "TwoFactor"; + + _userProfile = { + //id: decodedToken.nameid, + //email: decodedToken.email, + //twoFactor: twoFactor + }; + + if (!twoFactor && profile) { + loadProfile(profile, callback); + } + else if (!twoFactor && !profile) { + loadProfile({}, callback); + //apiService.accounts.getProfile({}, function (response) { + // loadProfile(response, callback); + //}); + } + }); + + function loadProfile(profile, callback) { + _userProfile.extended = { + name: profile.Name, + twoFactorEnabled: profile.TwoFactorEnabled, + culture: profile.Culture + }; + + callback(); + } + }; + + UserService.prototype.clearUserProfile = function () { + _userProfile = null; + }; + + UserService.prototype.isAuthenticated = function (callback) { + if (!callback || typeof callback !== 'function') { + throw 'callback function required'; + } + + this.getUserProfile(function (profile) { + callback(profile !== null && !profile.twoFactor); + }); + }; + + UserService.prototype.isTwoFactorAuthenticated = function (callback) { + if (!callback || typeof callback !== 'function') { + throw 'callback function required'; + } + + this.getUserProfile(function (profile) { + callback(profile !== null && profile.twoFactor); + }); + }; +}();