backupFile

This commit is contained in:
antelle 2016-08-21 18:43:59 +03:00
parent 26fad0c5fa
commit 24d18cd296
5 changed files with 133 additions and 49 deletions

View File

@ -317,6 +317,10 @@ var DropboxLink = {
this._callAndHandleError('remove', [fileName], complete);
},
mkdir: function(path, complete) {
this._callAndHandleError('mkdir', [path], complete);
},
canChooseFile: function() {
return !Launcher;
},

View File

@ -16,6 +16,7 @@ var Backbone = require('backbone'),
Logger = require('../util/logger'),
FeatureDetector = require('../util/feature-detector'),
Format = require('../util/format'),
UrlUtil = require('../util/url-util'),
AutoType = require('../auto-type');
require('../mixins/protected-value-ex');
@ -784,13 +785,47 @@ var AppModel = Backbone.Model.extend({
}
let path = backup.path.replace('{date}', Format.dtStrFs(new Date()));
logger.info('Backup file to', backup.storage, path);
Storage[backup.storage].save(path, opts, data, (err) => {
if (err) {
logger.error('Backup error', err);
} else {
logger.info('Backup complete');
let saveToFolder = () => {
if (Storage[backup.storage].getPathForName) {
path = Storage[backup.storage].getPathForName(path);
}
Storage[backup.storage].save(path, opts, data, (err) => {
if (err) {
logger.error('Backup error', err);
} else {
logger.info('Backup complete');
}
callback(err);
});
};
let folderPath = UrlUtil.fileToDir(path);
if (Storage[backup.storage].getPathForName) {
folderPath = Storage[backup.storage].getPathForName(folderPath).replace('.kdbx', '');
}
Storage[backup.storage].stat(folderPath, opts, (err) => {
if (err) {
if (err.notFound) {
logger.info('Backup folder does not exist');
if (!Storage[backup.storage].mkdir) {
return callback('Mkdir not supported by ' + backup.storage);
}
Storage[backup.storage].mkdir(folderPath, (err) => {
if (err) {
logger.error('Error creating backup folder', err);
callback('Error creating backup folder');
} else {
logger.info('Backup folder created');
saveToFolder();
}
});
} else {
logger.error('Stat folder error', err);
callback('Cannot stat backup folder');
}
} else {
logger.info('Backup folder exists, saving');
saveToFolder();
}
callback(err);
});
}
});

View File

@ -215,6 +215,19 @@ var StorageDropbox = StorageBase.extend({
}, _.noop);
},
mkdir: function(path, callback) {
DropboxLink.authenticate((err) => {
if (err) { return callback(err); }
this.logger.debug('Make dir', path);
let ts = this.logger.ts();
path = this._toFullPath(path);
DropboxLink.mkdir(path, err => {
this.logger.debug('Made dir', path, this.logger.ts(ts));
return callback && callback(err);
}, _.noop);
});
},
setEnabled: function(enabled) {
if (!enabled) {
DropboxLink.logout();

View File

@ -71,52 +71,59 @@ var StorageGDrive = StorageBase.extend({
},
save: function(path, opts, data, callback, rev) {
this.stat(path, opts, (err, stat) => {
if (rev) {
if (err) { return callback && callback(err); }
if (stat.rev !== rev) {
return callback && callback({revConflict: true}, stat);
}
this._oauthAuthorize(err => {
if (err) {
return callback && callback(err);
}
this.logger.debug('Save', path);
var ts = this.logger.ts();
var isNew = path.lastIndexOf(NewFileIdPrefix, 0) === 0;
var url;
if (isNew) {
url = 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,headRevisionId';
var fileName = path.replace(NewFileIdPrefix, '') + '.kdbx';
var boundry = 'b' + Date.now() + 'x' + Math.round(Math.random() * 1000000);
data = new Blob([
'--', boundry, '\r\n',
'Content-Type: application/json; charset=UTF-8', '\r\n\r\n',
JSON.stringify({ name: fileName }), '\r\n',
'--', boundry, '\r\n',
'Content-Type: application/octet-stream', '\r\n\r\n',
data, '\r\n',
'--', boundry, '--', '\r\n'
], {type: 'multipart/related; boundary="' + boundry + '"'});
} else {
url = 'https://www.googleapis.com/upload/drive/v3/files/{id}?uploadType=media&fields=headRevisionId'
.replace('{id}', path);
data = new Blob([data], {type: 'application/octet-stream'});
}
this._xhr({
url: url,
method: isNew ? 'POST' : 'PATCH',
responseType: 'json',
data: data,
success: (response) => {
this.logger.debug('Saved', path, this.logger.ts(ts));
var newRev = response.headRevisionId;
if (!newRev) {
return callback && callback('save error: no rev');
this.stat(path, opts, (err, stat) => {
if (rev) {
if (err) {
return callback && callback(err);
}
if (stat.rev !== rev) {
return callback && callback({ revConflict: true }, stat);
}
return callback && callback(null, { rev: newRev, path: isNew ? response.id : null });
},
error: (err) => {
this.logger.error('Save error', path, err, this.logger.ts(ts));
return callback && callback(err);
}
this.logger.debug('Save', path);
var ts = this.logger.ts();
var isNew = path.lastIndexOf(NewFileIdPrefix, 0) === 0;
var url;
if (isNew) {
url = 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,headRevisionId';
var fileName = path.replace(NewFileIdPrefix, '') + '.kdbx';
var boundry = 'b' + Date.now() + 'x' + Math.round(Math.random() * 1000000);
data = new Blob([
'--', boundry, '\r\n',
'Content-Type: application/json; charset=UTF-8', '\r\n\r\n',
JSON.stringify({ name: fileName }), '\r\n',
'--', boundry, '\r\n',
'Content-Type: application/octet-stream', '\r\n\r\n',
data, '\r\n',
'--', boundry, '--', '\r\n'
], { type: 'multipart/related; boundary="' + boundry + '"' });
} else {
url = 'https://www.googleapis.com/upload/drive/v3/files/{id}?uploadType=media&fields=headRevisionId'
.replace('{id}', path);
data = new Blob([data], { type: 'application/octet-stream' });
}
this._xhr({
url: url,
method: isNew ? 'POST' : 'PATCH',
responseType: 'json',
data: data,
success: (response) => {
this.logger.debug('Saved', path, this.logger.ts(ts));
var newRev = response.headRevisionId;
if (!newRev) {
return callback && callback('save error: no rev');
}
return callback && callback(null, { rev: newRev, path: isNew ? response.id : null });
},
error: (err) => {
this.logger.error('Save error', path, err, this.logger.ts(ts));
return callback && callback(err);
}
});
});
});
},

View File

@ -190,6 +190,31 @@ var StorageOneDrive = StorageBase.extend({
});
},
mkdir: function(path, callback) {
this._oauthAuthorize(err => {
if (err) { return callback && callback(err); }
this.logger.debug('Make dir', path);
var ts = this.logger.ts();
var url = this._baseUrl + '/drive/root/children';
var data = JSON.stringify({ name: path.replace('/drive/root:/', ''), folder: {} });
this._xhr({
url: url,
method: 'POST',
responseType: 'json',
statuses: [200, 204],
data: new Blob([data], {type: 'application/json'}),
success: () => {
this.logger.debug('Made dir', path, this.logger.ts(ts));
return callback && callback();
},
error: (err) => {
this.logger.error('Make dir error', path, err, this.logger.ts(ts));
return callback && callback(err);
}
});
});
},
setEnabled: function(enabled) {
if (!enabled) {
var url = 'https://login.live.com/oauth20_logout.srf?client_id={client_id}&redirect_uri={url}'