From 6af880a25c6ebb71fc5d05ffc983620da02cbc58 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Sat, 25 Feb 2017 22:19:47 -0600 Subject: [PATCH] remove restangular as dependency, use xmlhttprequest --- Gruntfile.js | 1 - app/assets/javascripts/app/app.frontend.js | 21 +---- .../javascripts/app/services/authManager.js | 53 ++++++------- .../app/services/extensionManager.js | 46 ++++++----- .../javascripts/app/services/httpManager.js | 79 +++++++++++++++++++ .../javascripts/app/services/syncManager.js | 75 +++++++++++++++--- bower.json | 2 +- 7 files changed, 189 insertions(+), 88 deletions(-) create mode 100644 app/assets/javascripts/app/services/httpManager.js diff --git a/Gruntfile.js b/Gruntfile.js index 197c493ce..aa8abae4c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -85,7 +85,6 @@ module.exports = function(grunt) { 'vendor/assets/bower_components/angular/angular.js', 'vendor/assets/bower_components/angular-ui-router/release/angular-ui-router.js', 'vendor/assets/bower_components/lodash/dist/lodash.min.js', - 'vendor/assets/bower_components/restangular/dist/restangular.js', 'vendor/assets/javascripts/crypto/*.js' ], dest: 'vendor/assets/javascripts/lib.js', diff --git a/app/assets/javascripts/app/app.frontend.js b/app/assets/javascripts/app/app.frontend.js index da2051625..701704207 100644 --- a/app/assets/javascripts/app/app.frontend.js +++ b/app/assets/javascripts/app/app.frontend.js @@ -14,24 +14,5 @@ if(!IEOrEdge && (window.crypto && window.crypto.subtle)) { } angular.module('app.frontend', [ - 'ui.router', - 'restangular' + 'ui.router' ]) - -.config(function (RestangularProvider, authManagerProvider) { - RestangularProvider.setDefaultHeaders({"Content-Type": "application/json"}); - - RestangularProvider.setFullRequestInterceptor(function(element, operation, route, url, headers, params, httpConfig) { - var token = localStorage.getItem("jwt"); - if(token) { - headers = _.extend(headers, {Authorization: "Bearer " + localStorage.getItem("jwt")}); - } - - return { - element: element, - params: params, - headers: headers, - httpConfig: httpConfig - }; - }); -}) diff --git a/app/assets/javascripts/app/services/authManager.js b/app/assets/javascripts/app/services/authManager.js index 5a9d1bde2..f9e57864c 100644 --- a/app/assets/javascripts/app/services/authManager.js +++ b/app/assets/javascripts/app/services/authManager.js @@ -7,11 +7,11 @@ angular.module('app.frontend') return domain; } - this.$get = function($rootScope, Restangular, modelManager) { - return new AuthManager($rootScope, Restangular, modelManager); + this.$get = function($rootScope, httpManager, modelManager) { + return new AuthManager($rootScope, httpManager, modelManager); } - function AuthManager($rootScope, Restangular, modelManager) { + function AuthManager($rootScope, httpManager, modelManager) { var userData = localStorage.getItem("user"); if(userData) { @@ -34,12 +34,10 @@ angular.module('app.frontend') this.getAuthParamsForEmail = function(url, email, callback) { var requestUrl = url + "/auth/params"; - var request = Restangular.oneUrl(requestUrl, requestUrl); - request.get({email: email}).then(function(response){ - callback(response.plain()); - }) - .catch(function(response){ - console.log("Error getting auth params", response); + httpManager.getAbsolute(requestUrl, {email: email}, function(response){ + callback(response); + }, function(response){ + console.error("Error getting auth params", response); callback(null); }) } @@ -74,17 +72,15 @@ angular.module('app.frontend') Neeto.crypto.computeEncryptionKeysForUser(_.merge({password: password}, authParams), function(keys){ var requestUrl = url + "/auth/sign_in"; - var request = Restangular.oneUrl(requestUrl, requestUrl); var params = {password: keys.pw, email: email}; - _.merge(request, params); - request.post().then(function(response){ + httpManager.postAbsolute(requestUrl, params, function(response){ this.handleAuthResponse(response, email, url, authParams, keys.mk, keys.pw); callback(response); - }.bind(this)) - .catch(function(response){ - console.log("Error logging in", response); - callback(response.data); + }.bind(this), function(response){ + console.error("Error logging in", response); + callback(null); }) + }.bind(this)); }.bind(this)) } @@ -93,7 +89,7 @@ angular.module('app.frontend') if(url) { localStorage.setItem("server", url); } - localStorage.setItem("user", JSON.stringify(response.plain().user)); + localStorage.setItem("user", JSON.stringify(response.user)); localStorage.setItem("auth_params", JSON.stringify(_.omit(authParams, ["pw_nonce"]))); localStorage.setItem("mk", mk); localStorage.setItem("pw", pw); @@ -103,15 +99,13 @@ angular.module('app.frontend') this.register = function(url, email, password, callback) { Neeto.crypto.generateInitialEncryptionKeysForUser({password: password, email: email}, function(keys, authParams){ var requestUrl = url + "/auth"; - var request = Restangular.oneUrl(requestUrl, requestUrl); var params = _.merge({password: keys.pw, email: email}, authParams); - _.merge(request, params); - request.post().then(function(response){ + + httpManager.postAbsolute(requestUrl, params, function(response){ this.handleAuthResponse(response, email, url, authParams, keys.mk, keys.pw); callback(response); - }.bind(this)) - .catch(function(response){ - console.log("Registration error", response); + }.bind(this), function(response){ + console.error("Registration error", response); callback(null); }) }.bind(this)); @@ -120,23 +114,20 @@ angular.module('app.frontend') this.changePassword = function(email, new_password, callback) { Neeto.crypto.generateInitialEncryptionKeysForUser({password: new_password, email: email}, function(keys, authParams){ var requestUrl = localStorage.getItem("server") + "/auth/change_pw"; - var request = Restangular.oneUrl(requestUrl, requestUrl); var params = _.merge({new_password: keys.pw}, authParams); - _.merge(request, params); - request.post().then(function(response){ + httpManager.postAbsolute(requestUrl, params, function(response){ this.handleAuthResponse(response, email, null, authParams, keys.mk, keys.pw); - callback(response.plain()); - }.bind(this)) - .catch(function(response){ + callback(response); + }.bind(this), function(response){ var error = response.data; if(!error) { error = {message: "Something went wrong while changing your password. Your password was not changed. Please try again."} } - console.log("Change pw error", response); + console.error("Change pw error", response); callback({error: error}); }) - }.bind(this)); + }) } this.staticifyObject = function(object) { diff --git a/app/assets/javascripts/app/services/extensionManager.js b/app/assets/javascripts/app/services/extensionManager.js index 20b21de82..17d2ab589 100644 --- a/app/assets/javascripts/app/services/extensionManager.js +++ b/app/assets/javascripts/app/services/extensionManager.js @@ -1,7 +1,7 @@ class ExtensionManager { - constructor(Restangular, modelManager, authManager, syncManager) { - this.Restangular = Restangular; + constructor(httpManager, modelManager, authManager, syncManager) { + this.httpManager = httpManager; this.modelManager = modelManager; this.authManager = authManager; this.enabledRepeatActionUrls = JSON.parse(localStorage.getItem("enabledRepeatActionUrls")) || []; @@ -77,11 +77,11 @@ class ExtensionManager { relevant just to this item. The response extension is not saved, just displayed as a one-time thing. */ loadExtensionInContextOfItem(extension, item, callback) { - this.Restangular.oneUrl(extension.url, extension.url).customGET("", {content_type: item.content_type, item_uuid: item.uuid}).then(function(response){ - var scopedExtension = new Extension(response.plain()); + + this.httpManager.getAbsolute(extension.url, {content_type: item.content_type, item_uuid: item.uuid}, function(response){ + var scopedExtension = new Extension(response); callback(scopedExtension); - }.bind(this)) - .catch(function(response){ + }, function(response){ console.log("Error loading extension", response); callback(null); }) @@ -91,14 +91,13 @@ class ExtensionManager { Registers new extension and saves it to user's account */ retrieveExtensionFromServer(url, callback) { - this.Restangular.oneUrl(url, url).get().then(function(response){ + this.httpManager.getAbsolute(url, {}, function(response){ var ext = this.handleExtensionLoadExternalResponseItem(url, response.plain()); if(callback) { callback(ext); } - }.bind(this)) - .catch(function(response){ - console.log("Error registering extension", response); + }.bind(this), function(response){ + console.error("Error registering extension", response); callback(null); }) } @@ -150,7 +149,8 @@ class ExtensionManager { switch (action.verb) { case "get": { - this.Restangular.oneUrl(action.url, action.url).get().then(function(response){ + + this.httpManager.getAbsolute(action.url, {}, function(response){ action.error = false; var items = response.items || [response.item]; EncryptionHelper.decryptMultipleItems(items, localStorage.getItem("mk")); @@ -160,8 +160,7 @@ class ExtensionManager { } this.syncManager.sync(null); customCallback({items: items}); - }.bind(this)) - .catch(function(response){ + }.bind(this), function(response){ action.error = true; customCallback(null); }) @@ -170,13 +169,14 @@ class ExtensionManager { } case "render": { - this.Restangular.oneUrl(action.url, action.url).get().then(function(response){ + + this.httpManager.getAbsolute(action.url, {}, function(response){ action.error = false; EncryptionHelper.decryptItem(response.item, localStorage.getItem("mk")); var item = this.modelManager.createItem(response.item); customCallback({item: item}); - }.bind(this)) - .catch(function(response){ + + }.bind(this), function(response){ action.error = true; customCallback(null); }) @@ -310,19 +310,17 @@ class ExtensionManager { } performPost(action, extension, params, callback) { - var request = this.Restangular.oneUrl(action.url, action.url); - if(this.extensionUsesEncryptedData(extension)) { - request.auth_params = this.authManager.getAuthParams(); - } - _.merge(request, params); - request.post().then(function(response){ + if(this.extensionUsesEncryptedData(extension)) { + params.auth_params = this.authManager.getAuthParams(); + } + + this.httpManager.postAbsolute(action.url, params, function(response){ action.error = false; if(callback) { callback(response.plain()); } - }) - .catch(function(response){ + }.bind(this), function(response){ action.error = true; console.log("Action error response:", response); if(callback) { diff --git a/app/assets/javascripts/app/services/httpManager.js b/app/assets/javascripts/app/services/httpManager.js new file mode 100644 index 000000000..15614ad9f --- /dev/null +++ b/app/assets/javascripts/app/services/httpManager.js @@ -0,0 +1,79 @@ +class HttpManager { + + setBaseUrl(baseUrl) { + this.baseUrl = baseUrl; + } + + setAuthHeadersForRequest(request) { + var token = localStorage.getItem("jwt"); + if(token) { + request.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem("jwt")); + } + } + + postAbsolute(url, params, onsuccess, onerror) { + var xmlhttp = new XMLHttpRequest(); + + xmlhttp.onreadystatechange = function() { + if (xmlhttp.readyState == 4) { + console.log("on ready state", xmlhttp.readyState, "text:", xmlhttp.responseText); + var response = xmlhttp.responseText; + if(response) { + response = JSON.parse(response); + } + + if(xmlhttp.status == 200){ + console.log("onsuccess", response); + onsuccess(response); + } else { + console.error("onerror", response); + onerror(response) + } + } + } + + xmlhttp.open("post", url, true); + this.setAuthHeadersForRequest(xmlhttp); + xmlhttp.setRequestHeader('Content-type', 'application/json'); + xmlhttp.send(JSON.stringify(params)); + } + + getAbsolute(url, params, onsuccess, onerror) { + + var formatParams = function(params) { + return "?" + Object + .keys(params) + .map(function(key){ + return key+"="+params[key] + }) + .join("&") + } + + var xmlhttp = new XMLHttpRequest(); + + xmlhttp.onreadystatechange = function() { + if (xmlhttp.readyState == 4) { + var response = xmlhttp.responseText; + if(response) { + response = JSON.parse(response); + } + + if(xmlhttp.status == 200){ + console.log("onsuccess", response); + onsuccess(response); + } else { + console.error("onerror", response); + onerror(response) + } + } + } + console.log("getting", url + formatParams(params)); + xmlhttp.open("get", url + formatParams(params), true); + this.setAuthHeadersForRequest(xmlhttp); + xmlhttp.setRequestHeader('Content-type', 'application/json'); + xmlhttp.send(); + } + +} + +angular.module('app.frontend').service('httpManager', HttpManager); diff --git a/app/assets/javascripts/app/services/syncManager.js b/app/assets/javascripts/app/services/syncManager.js index ddabf436d..87def65e0 100644 --- a/app/assets/javascripts/app/services/syncManager.js +++ b/app/assets/javascripts/app/services/syncManager.js @@ -1,10 +1,10 @@ class SyncManager { - constructor($rootScope, modelManager, authManager, dbManager, Restangular) { + constructor($rootScope, modelManager, authManager, dbManager, httpManager) { this.$rootScope = $rootScope; + this.httpManager = httpManager; this.modelManager = modelManager; this.authManager = authManager; - this.Restangular = Restangular; this.dbManager = dbManager; this.syncStatus = {}; } @@ -161,18 +161,18 @@ class SyncManager { this.syncStatus.current = 0; } - var request = this.Restangular.oneUrl(this.syncURL, this.syncURL); - request.limit = 150; - request.items = _.map(subItems, function(item){ + var params = {}; + params.limit = 150; + params.items = _.map(subItems, function(item){ var itemParams = new ItemParams(item, localStorage.getItem("mk")); itemParams.additionalFields = options.additionalFields; return itemParams.paramsForSync(); }.bind(this)); - request.sync_token = this.syncToken; - request.cursor_token = this.cursorToken; + params.sync_token = this.syncToken; + params.cursor_token = this.cursorToken; - request.post().then(function(response) { + this.httpManager.postAbsolute(this.syncURL, params, function(response){ this.modelManager.clearDirtyItems(subItems); this.syncStatus.error = null; @@ -211,8 +211,7 @@ class SyncManager { this.callQueuedCallbacksAndCurrent(callback, response); } - }.bind(this)) - .catch(function(response){ + }.bind(this), function(response){ console.log("Sync error: ", response); var error = response.data ? response.data.error : {message: "Could not connect to server."}; @@ -223,7 +222,61 @@ class SyncManager { this.$rootScope.$broadcast("sync:error", error); this.callQueuedCallbacksAndCurrent(callback, {error: "Sync error"}); - }.bind(this)) + }.bind(this)); + + // + // request.post().then(function(response) { + // this.modelManager.clearDirtyItems(subItems); + // this.syncStatus.error = null; + // + // this.$rootScope.$broadcast("sync:updated_token", this.syncToken); + // + // var retrieved = this.handleItemsResponse(response.retrieved_items, null); + // + // // merge only metadata for saved items + // // we write saved items to disk now because it clears their dirty status then saves + // // if we saved items before completion, we had have to save them as dirty and save them again on success as clean + // var omitFields = ["content", "auth_hash"]; + // var saved = this.handleItemsResponse(response.saved_items, omitFields); + // + // this.handleUnsavedItemsResponse(response.unsaved) + // + // this.writeItemsToLocalStorage(saved, false, null); + // this.writeItemsToLocalStorage(retrieved, false, null); + // + // this.syncStatus.syncOpInProgress = false; + // this.syncStatus.current += subItems.length; + // + // // set the sync token at the end, so that if any errors happen above, you can resync + // this.syncToken = response.sync_token; + // this.cursorToken = response.cursor_token; + // + // if(this.cursorToken || this.syncStatus.needsMoreSync) { + // setTimeout(function () { + // this.sync(callback, options); + // }.bind(this), 10); // wait 10ms to allow UI to update + // } else if(this.repeatOnCompletion) { + // this.repeatOnCompletion = false; + // setTimeout(function () { + // this.sync(callback, options); + // }.bind(this), 10); // wait 10ms to allow UI to update + // } else { + // this.callQueuedCallbacksAndCurrent(callback, response); + // } + // + // }.bind(this)) + // .catch(function(response){ + // console.log("Sync error: ", response); + // var error = response.data ? response.data.error : {message: "Could not connect to server."}; + // + // this.syncStatus.syncOpInProgress = false; + // this.syncStatus.error = error; + // this.writeItemsToLocalStorage(allDirtyItems, false, null); + // + // this.$rootScope.$broadcast("sync:error", error); + // + // this.callQueuedCallbacksAndCurrent(callback, {error: "Sync error"}); + // }.bind(this)) } handleUnsavedItemsResponse(unsaved) { diff --git a/bower.json b/bower.json index fa8d65b8f..22dfd09a5 100644 --- a/bower.json +++ b/bower.json @@ -9,7 +9,7 @@ "dependencies": { "angular": "1.6.1", "angular-ui-router": "^0.3.2", - "restangular": "^1.6.1" + "lodash" : "^4.17.4" }, "resolutions": { "angular": "1.6.1"