diff --git a/src/background.js b/src/background.js
index 5f282702..077ada5c 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 a3ba091a..00000000
--- 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 3fd194ba..00000000
--- 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 a5f5c3b5..2e50e396 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 00000000..1768c330
--- /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 e6b4c6b9..a907cb90 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 00000000..f55de6fa
--- /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 00000000..f1a1ef26
--- /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 00000000..12168099
--- /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 00000000..ca9620dc
--- /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 00000000..49effbfd
--- /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 00000000..c2fd3310
--- /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 4dac44e5..5903f604 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 8f29b9dc..00000000
--- 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 33370a20..fcf9bb5a 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 2ba7b09b..597c38c1 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 00000000..89b765be
--- /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);
+ });
+ };
+}();