Merge pull request #1913 from matiu/feature/quota

Feature/quota
This commit is contained in:
Gustavo Maximiliano Cortez 2014-12-02 09:46:11 -03:00
commit 17614d2968
13 changed files with 162 additions and 32 deletions

View file

@ -41,7 +41,7 @@ angular.module('copayApp.controllers').controller('CreateController',
$scope.create = function(form) {
if (form && form.$invalid) {
notification.error('Error', 'Please enter the required fields');
$scope.error = 'Please enter the required fields';
return;
}
var opts = {
@ -56,7 +56,11 @@ angular.module('copayApp.controllers').controller('CreateController',
$rootScope.starting = false;
if (err || !wallet) {
copay.logger.debug(err);
$scope.error = 'Could not create wallet.' + err;
if (err.match('OVERQUOTA')){
$scope.error = 'Could not create wallet: storage limits on remove server exceeded';
} else {
$scope.error = 'Could not create wallet: ' + err;
}
}
$rootScope.$digest()
});

View file

@ -18,6 +18,7 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
$scope.done = function() {
$rootScope.starting = false;
$rootScope.$digest();
};
@ -46,11 +47,13 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
} else {
$scope.error = 'Unknown error';
}
return $scope.done();
}
if (iden) {
iden.on('newWallet', $scope.done);
iden.on('noWallets', $scope.done);
iden.openWallets();
}
});
}

View file

@ -1,5 +1,5 @@
'use strict';
angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, backupService, identityService) {
angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, $filter, backupService, identityService) {
$scope.username = $rootScope.iden.getName();
$scope.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
@ -20,16 +20,35 @@ angular.module('copayApp.controllers').controller('ProfileController', function(
identityService.deleteWallet(w, function(err) {
$scope.loading = false;
if (err) {
log.warn(err);
copay.logger.warn(err);
}
$scope.setWallets();
});
};
$scope.init = function() {
if ($rootScope.quotaPerItem) {
$scope.perItem = $filter('noFractionNumber')($rootScope.quotaPerItem/1000,1);
$scope.nrWallets =parseInt($rootScope.quotaItems) - 1;
}
};
$scope.setWallets = function() {
if (!$rootScope.iden) return;
$scope.wallets=$rootScope.iden.listWallets();
};
var wallets = $rootScope.iden.listWallets();
var max =$rootScope.quotaPerItem;
_.each(wallets, function(w) {
var bits = w.sizes().total;
w.kb = $filter('noFractionNumber')(bits/1000, 1);
if (max) {
w.usage = $filter('noFractionNumber')(bits/max * 100, 0);
}
});
$scope.wallets = wallets;
};
$scope.downloadWalletBackup = function(w) {
if (!w) return;

View file

@ -122,7 +122,7 @@ Identity.open = function(opts, cb) {
var storage = opts.storage || opts.pluginManager.get('DB');
storage.setCredentials(opts.email, opts.password, opts);
storage.getItem(Identity.getKeyForEmail(opts.email), function(err, data) {
storage.getItem(Identity.getKeyForEmail(opts.email), function(err, data, headers) {
var exported;
if (err) {
return cb(err);
@ -132,7 +132,7 @@ Identity.open = function(opts, cb) {
} catch (e) {
return cb(e);
}
return cb(null, new Identity(_.extend(opts, exported)));
return cb(null, new Identity(_.extend(opts, exported)), headers);
});
};
@ -619,11 +619,10 @@ Identity.prototype.deleteWallet = function(walletId, cb) {
delete this.focusedTimestamps[walletId];
this.storage.removeItem(Wallet.getStorageKey(walletId), function(err) {
if (err) {
return cb(err);
}
if (err) return cb(err);
self.emitAndKeepAlive('deletedWallet', walletId);
self.store(null, cb);
return cb();
});
};

View file

@ -20,7 +20,7 @@ EncryptedInsightStorage.prototype._brokenDecrypt = function(body) {
EncryptedInsightStorage.prototype.getItem = function(name, callback) {
var self = this;
InsightStorage.prototype.getItem.apply(this, [name,
function(err, body) {
function(err, body, headers) {
if (err) {
return callback(err);
}
@ -35,7 +35,7 @@ EncryptedInsightStorage.prototype.getItem = function(name, callback) {
log.debug('Could not decrypt value.');
return callback('PNOTFOUND');
}
return callback(null, decryptedJson);
return callback(null, decryptedJson, headers);
}
]);
};

View file

@ -46,12 +46,12 @@ InsightStorage.prototype.getItem = function(name, callback) {
var passphrase = this.getPassphrase();
var self = this;
this._makeGetRequest(passphrase, name, function(err, body) {
if (err) log.info('[InsightStorage. err]', err);
this._makeGetRequest(passphrase, name, function(err, body, headers) {
if (err) log.warn(err);
if (err && err.indexOf('PNOTFOUND') !== -1 && mayBeOldPassword(self.password)) {
return self._brokenGetItem(name, callback);
}
return callback(err, body);
return callback(err, body, headers);
});
};
@ -74,6 +74,30 @@ InsightStorage.prototype.getPassphrase = function() {
return bitcore.util.twoSha256(this.getKey()).toString('base64');
};
/**
* XmlHttpRequest's getAllResponseHeaders() method returns a string of response
* headers according to the format described here:
* http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method
* This method parses that string into a user-friendly key/value pair object.
*/
InsightStorage.parseResponseHeaders = function (headerStr) {
var headers = {};
if (!headerStr) {
return headers;
}
var headerPairs = headerStr.split('\u000d\u000a');
for (var i = 0, len = headerPairs.length; i < len; i++) {
var headerPair = headerPairs[i];
var index = headerPair.indexOf('\u003a\u0020');
if (index > 0) {
var key = headerPair.substring(0, index);
var val = headerPair.substring(index + 2);
headers[key] = val;
}
}
return headers;
}
InsightStorage.prototype._makeGetRequest = function(passphrase, key, callback) {
var authHeader = new buffers.Buffer(this.email + ':' + passphrase).toString('base64');
var retrieveUrl = this.storeUrl + '/retrieve';
@ -96,7 +120,7 @@ InsightStorage.prototype._makeGetRequest = function(passphrase, key, callback) {
if (response.statusCode !== 200) {
return callback('Connection error');
}
return callback(null, body);
return callback(null, body, InsightStorage.parseResponseHeaders(response.getAllResponseHeaders()));
}
);
};
@ -172,16 +196,39 @@ InsightStorage.prototype.setItem = function(name, value, callback) {
}
if (response.statusCode === 409) {
return callback('BADCREDENTIALS: Invalid username or password');
}
if (response.statusCode !== 200) {
} else if (response.statusCode === 406) {
return callback('OVERQUOTA: Quota exceeded');
} else if (response.statusCode !== 200) {
return callback('Unable to store data on insight');
}
return callback();
});
};
InsightStorage.prototype.removeItem = function(name, callback) {
this.setItem(name, '', callback);
InsightStorage.prototype.removeItem = function(key, callback) {
var passphrase = this.getPassphrase();
var authHeader = new buffers.Buffer(this.email + ':' + passphrase).toString('base64');
var deleteUrl = this.storeUrl + '/delete/item';
var getParams = {
url: deleteUrl + '?' + querystring.encode({
key: key
}),
headers: {
'Authorization': authHeader
}
};
log.debug('erase ' + name);
this.request.get(getParams, function(err, response, body) {
if (err) {
return callback('Connection error');
}
if (response.statusCode === 409) {
return callback('BADCREDENTIALS: Invalid username or password');
} else if (response.statusCode !== 200) {
return callback('Unable to remove data on insight');
}
return callback();
});
};
InsightStorage.prototype.clear = function(callback) {

View file

@ -67,6 +67,21 @@ angular.module('copayApp.services')
};
root.setServerStatus = function(headers) {
if (!headers)
return;
if (headers['X-Email-Needs-Validation'])
$rootScope.needsEmailConfirmation = true;
else
$rootScope.needsEmailConfirmation = null;
if (headers['X-Quota-Per-Item'])
$rootScope.quotaPerItem = parseInt(headers['X-Quota-Per-Item']);
if (headers['X-Quota-Items-Limit'])
$rootScope.quotaItems = parseInt(headers['X-Quota-Items-Limit']);
};
root.open = function(email, password, cb) {
var opts = {
@ -79,11 +94,11 @@ angular.module('copayApp.services')
passphraseConfig: config.passphraseConfig,
};
copay.Identity.open(opts, function(err, iden) {
copay.Identity.open(opts, function(err, iden, headers) {
if (err) return cb(err);
root.setServerStatus(headers);
root.bind(iden);
iden.openWallets();
return cb();
return cb(null, iden);
});
};
@ -251,7 +266,6 @@ angular.module('copayApp.services')
copay.logger.debug('newWallet:', w.getName(), wid, iden.getLastFocusedWalletId());
root.installWalletHandlers(w);
if (wid == iden.getLastFocusedWalletId()) {
$rootScope.starting = false;
copay.logger.debug('GOT Focused wallet:', w.getName());
root.setFocusedWallet(w, true);
root.goWalletHome();