Improved Google Drive autobackup.
This commit is contained in:
parent
edd018e35a
commit
bf87bbd4a3
42
db.js
42
db.js
|
@ -1385,10 +1385,10 @@ module.exports.CreateDB = function (parent, func) {
|
|||
}
|
||||
|
||||
// Perform cloud backup
|
||||
obj.performCloudBackup = function(filename) {
|
||||
if (parent.config.settings.autobackup.googledrive != true) return;
|
||||
obj.performCloudBackup = function (filename) {
|
||||
if (typeof parent.config.settings.autobackup.googledrive != 'object') return;
|
||||
obj.Get('GoogleDriveBackup', function (err, docs) {
|
||||
if ((err != null) || (docs.length != 1) || (docs[0].state == 3)) return;
|
||||
if ((err != null) || (docs.length != 1) || (docs[0].state != 3)) return;
|
||||
const {google} = require('googleapis');
|
||||
const oAuth2Client = new google.auth.OAuth2(docs[0].clientid, docs[0].clientsecret, "urn:ietf:wg:oauth:2.0:oob");
|
||||
oAuth2Client.on('tokens', function(tokens) { if (tokens.refresh_token) { docs[0].token = tokens.refresh_token; parent.db.Set(docs[0]); } }); // Update the token in the database
|
||||
|
@ -1398,36 +1398,44 @@ module.exports.CreateDB = function (parent, func) {
|
|||
|
||||
// Called once we know our folder id, clean up and upload a backup.
|
||||
var useGoogleDrive = function (folderid) {
|
||||
// List files to see if we need to delete some
|
||||
drive.files.list({
|
||||
q: 'trashed = false and \'' + folderid + '\' in parents',
|
||||
fields: 'nextPageToken, files(id, name, size, createdTime)',
|
||||
}, function (err, res) {
|
||||
if (err) { console.log('GoogleDrive error: ' + err); return; }
|
||||
// Delete any old files if more than 10 files are present in the backup folder.
|
||||
res.data.files.sort(createdTimeSort);
|
||||
while (res.data.files.length > 10) { drive.files.delete({ fileId: res.data.files.shift().id }, function (err, res) { }); }
|
||||
});
|
||||
// List files to see if we need to delete older ones
|
||||
if (typeof parent.config.settings.autobackup.googledrive.maxfiles == 'number') {
|
||||
drive.files.list({
|
||||
q: 'trashed = false and \'' + folderid + '\' in parents',
|
||||
fields: 'nextPageToken, files(id, name, size, createdTime)',
|
||||
}, function (err, res) {
|
||||
if (err) { console.log('GoogleDrive (files.list) error: ' + err); return; }
|
||||
// Delete any old files if more than 10 files are present in the backup folder.
|
||||
res.data.files.sort(createdTimeSort);
|
||||
while (res.data.files.length >= parent.config.settings.autobackup.googledrive.maxfiles) { drive.files.delete({ fileId: res.data.files.shift().id }, function (err, res) { }); }
|
||||
});
|
||||
}
|
||||
|
||||
//console.log('Uploading...');
|
||||
// Upload the backup
|
||||
drive.files.create({
|
||||
requestBody: { name: require('path').basename(filename), mimeType: 'text/plain', parents: [folderid] },
|
||||
media: { mimeType: 'application/zip', body: require('fs').createReadStream(filename) },
|
||||
}, function (err, res) {
|
||||
if (err) { console.log('GoogleDrive error: ' + err); return; }
|
||||
if (err) { console.log('GoogleDrive (files.create) error: ' + err); return; }
|
||||
//console.log('Upload done.');
|
||||
});
|
||||
}
|
||||
|
||||
// Fetch the folder name
|
||||
var folderName = 'MeshCentral-Backups';
|
||||
if (typeof parent.config.settings.autobackup.googledrive.foldername == 'string') { folderName = parent.config.settings.autobackup.googledrive.foldername; }
|
||||
|
||||
// Find our backup folder, create one if needed.
|
||||
drive.files.list({
|
||||
q: 'mimeType = \'application/vnd.google-apps.folder\' and name=\'MeshCentral-Backups\' and trashed = false',
|
||||
q: 'mimeType = \'application/vnd.google-apps.folder\' and name=\'' + folderName + '\' and trashed = false',
|
||||
fields: 'nextPageToken, files(id, name)',
|
||||
}, function (err, res) {
|
||||
if (err) { console.log('GoogleDrive error: ' + err); return; }
|
||||
if (res.data.files.length == 0) {
|
||||
// Create a folder
|
||||
drive.files.create({ resource: { 'name': 'MeshCentral-Backups', 'mimeType': 'application/vnd.google-apps.folder' }, fields: 'id' }, function (err, file) {
|
||||
if (err) { console.log('GoogleDrive error: ' + err); return; }
|
||||
drive.files.create({ resource: { 'name': folderName, 'mimeType': 'application/vnd.google-apps.folder' }, fields: 'id' }, function (err, file) {
|
||||
if (err) { console.log('GoogleDrive (folder.create) error: ' + err); return; }
|
||||
useGoogleDrive(file.data.id);
|
||||
});
|
||||
} else { useGoogleDrive(res.data.files[0].id); }
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<html><head></head><body><div>[[[SERVERNAME]]] - Email Verification</div>
|
||||
<div style="font-family:Arial,Helvetica,sans-serif">
|
||||
<table style="background-color:#003366;color:lightgray;width:100%" cellpadding="8">
|
||||
<tbody><tr>
|
||||
<td>
|
||||
<b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Verification</b>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<p>Hi [[[USERNAME]]], <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting email verification, click on the following link to complete the process.</p>
|
||||
<p style="margin-left:30px">
|
||||
<a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]">Click here to verify your e-mail address.</a>
|
||||
</p>
|
||||
If you did not initiate this request, please ignore this mail.
|
||||
</div></body></html>
|
|
@ -0,0 +1,6 @@
|
|||
[[[SERVERNAME]]] - Email Verification
|
||||
Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process:
|
||||
~
|
||||
~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]
|
||||
~
|
||||
If you did not initiate this request, please ignore this mail.
|
|
@ -0,0 +1,19 @@
|
|||
<html><head></head><body><div>[[[SERVERNAME]]] - Account Invitation</div>
|
||||
<div style="font-family:Arial,Helvetica,sans-serif">
|
||||
<table style="background-color:#003366;color:lightgray;width:100%" cellpadding="8">
|
||||
<tbody><tr>
|
||||
<td>
|
||||
<b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Account Invitation</b>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<p>An account was created for you on server <a href="[[[SERVERURL]]]" notrans="1">[[[SERVERNAME]]]</a>, you can access it now with:</p>
|
||||
<p>
|
||||
Username: <b notrans="1">[[[ACCOUNTNAME]]]</b><br>
|
||||
Password: <b notrans="1">[[[PASSWORD]]]</b>
|
||||
</p>
|
||||
Best regards,
|
||||
<br>
|
||||
[[[USERNAME]]]
|
||||
<br>
|
||||
</div></body></html>
|
|
@ -0,0 +1,5 @@
|
|||
[[[SERVERNAME]]] - Account Invitation
|
||||
An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]".
|
||||
~
|
||||
Best regards,
|
||||
~[[[USERNAME]]]
|
|
@ -0,0 +1,12 @@
|
|||
<html><head></head><body><div>[[[SERVERNAME]]] - Account Login</div>
|
||||
<div style="font-family:Arial,Helvetica,sans-serif">
|
||||
<table style="background-color:#003366;color:lightgray;width:100%" cellpadding="8">
|
||||
<tbody><tr>
|
||||
<td>
|
||||
<b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Account Login</b>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<p>Your login token is: [[[TOKEN]]]</p>
|
||||
<p>This token can only be used once and is valid for 5 minutes.</p>
|
||||
</div></body></html>
|
|
@ -0,0 +1,4 @@
|
|||
[[[SERVERNAME]]] - Account Login
|
||||
Your login token is: [[[TOKEN]]]
|
||||
~
|
||||
This token can only be used once and is valid for 5 minutes.
|
|
@ -0,0 +1,15 @@
|
|||
<html><head></head><body><div>[[[SERVERNAME]]] - Account Reset</div>
|
||||
<div style="font-family:Arial,Helvetica,sans-serif">
|
||||
<table style="background-color:#003366;color:lightgray;width:100%" cellpadding="8">
|
||||
<tbody><tr>
|
||||
<td>
|
||||
<b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Verification</b>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<p>Hi [[[USERNAME]]], <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting an account password reset, click on the following link to complete the process.</p>
|
||||
<p style="margin-left:30px">
|
||||
<a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]">Click here to reset your account password.</a>
|
||||
</p>
|
||||
If you did not initiate this request, please ignore this mail.
|
||||
</div></body></html>
|
|
@ -0,0 +1,6 @@
|
|||
[[[SERVERNAME]]] - Account Reset
|
||||
Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process:
|
||||
~
|
||||
~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]
|
||||
~
|
||||
If you did not initiate this request, please ignore this mail.
|
|
@ -0,0 +1,42 @@
|
|||
<html><head></head><body><div>[[[SERVERNAME]]] - Invitation</div>
|
||||
<div style="font-family:Arial,Helvetica,sans-serif">
|
||||
<table style="background-color:#003366;color:lightgray;width:100%" cellpadding="8">
|
||||
<tbody><tr>
|
||||
<td>
|
||||
<b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Agent Installation</b>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
<area-name>
|
||||
<p>
|
||||
Hello [[[NAME]]],
|
||||
</p>
|
||||
</area-name>
|
||||
<p>User [[[USERNAME]]] on server <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting you to install software to start a remote control session.</p>
|
||||
<area-msg>
|
||||
<p>
|
||||
Message: <b notrans="1">[[[MSG]]]</b>
|
||||
</p>
|
||||
</area-msg>
|
||||
<area-windows>
|
||||
<p style="margin-left:30px">
|
||||
<a href="[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]">Click here to download the MeshAgent for Windows.</a>
|
||||
</p>
|
||||
</area-windows>
|
||||
<area-osx>
|
||||
<p style="margin-left:30px"><a href="[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]">Click here to download the MeshAgent for Apple OSX.</a></p>
|
||||
</area-osx>
|
||||
<area-linux>
|
||||
<p>
|
||||
For Linux, cut & paste the following in a terminal to install the agent:<br>
|
||||
</p><pre style="margin-left:30px" notrans="1">wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre>
|
||||
<p></p>
|
||||
</area-linux>
|
||||
<area-link>
|
||||
<p>
|
||||
To install the software, <a href="[[[SERVERURL]]][[[LINKURL]]]">click here</a> and follow the instructions.
|
||||
</p>
|
||||
</area-link>
|
||||
<p>If you did not initiate this request, please ignore this mail.</p>
|
||||
Best regards,<br>[[[USERNAME]]]<br>
|
||||
</div></body></html>
|
|
@ -0,0 +1,35 @@
|
|||
[[[SERVERNAME]]] - Invitation
|
||||
~<area-name>
|
||||
Hello [[[NAME]]],
|
||||
~</area-name>
|
||||
User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session.
|
||||
~<area-msg>
|
||||
~
|
||||
Message: [[[MSG]]]
|
||||
~
|
||||
~</area-msg>
|
||||
~<area-windows>
|
||||
For Windows, nagivate to the following link to complete the process:
|
||||
~
|
||||
~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]
|
||||
~
|
||||
~</area-windows>
|
||||
~<area-osx>
|
||||
For Apple OSX, nagivate to the following link to complete the process:
|
||||
~
|
||||
~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]
|
||||
~
|
||||
~</area-osx>
|
||||
~<area-linux>
|
||||
For Linux, cut & paste the following in a terminal to install the agent:
|
||||
~
|
||||
~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]'
|
||||
~
|
||||
~</area-linux>
|
||||
~<area-link>
|
||||
To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions.
|
||||
~</area-link>
|
||||
If you did not initiate this request, please ignore this mail.
|
||||
~
|
||||
Best regards,
|
||||
~[[[USERNAME]]]
|
|
@ -0,0 +1,2 @@
|
|||
[[0]] verification code is: [[1]]
|
||||
[[0]] access token is: [[1]]
|
|
@ -1397,13 +1397,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||
// Indicates if the agent has a coredump available
|
||||
if ((command.exists === true) && (typeof command.agenthashhex == 'string') && (command.agenthashhex.length == 96)) {
|
||||
// Check if we already have this exact dump file
|
||||
const coreDumpFile = parent.path.join(parent.parent.datapath, 'coredumps', obj.agentInfo.agentId + '-' + command.agenthashhex + '-' + obj.nodeid + '.dmp');
|
||||
const coreDumpFile = parent.path.join(parent.parent.datapath, '..', 'meshcentral-coredumps', obj.agentInfo.agentId + '-' + command.agenthashhex + '-' + obj.nodeid + '.dmp');
|
||||
parent.fs.stat(coreDumpFile, function (err, stats) {
|
||||
if (stats != null) return;
|
||||
obj.coreDumpPresent = true;
|
||||
|
||||
// Check how many files are in the coredumps folder
|
||||
const coreDumpPath = parent.path.join(parent.parent.datapath, 'coredumps');
|
||||
const coreDumpPath = parent.path.join(parent.parent.datapath, '..', 'meshcentral-coredumps');
|
||||
parent.fs.readdir(coreDumpPath, function (err, files) {
|
||||
if ((files != null) && (files.length >= 20)) return; // Don't get more than 20 core dump files.
|
||||
|
||||
|
|
|
@ -107,7 +107,15 @@
|
|||
"backupIntervalHours": { "type": "integer" },
|
||||
"keepLastDaysBackup": { "type": "integer" },
|
||||
"zipPassword": { "type": "string" },
|
||||
"backupPath": { "type": "string" }
|
||||
"backupPath": { "type": "string" },
|
||||
"googleDrive": {
|
||||
"type": "object",
|
||||
"description": "Enabled automated upload of the server backups to a Google Drive account, once enabled you need to go in \"My Server\" tab as administrator to associate the account.",
|
||||
"properties": {
|
||||
"folderName": { "type": "integer", "default": "MeshCentral-Backups", "description": "The name of the folder to create in the Google Drive account." },
|
||||
"maxFiles": { "type": "string", "default": null, "description": "The maximum number of files to keep in the Google Drive folder, older files will be removed if needed." }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"redirects": { "type": "object" },
|
||||
|
|
|
@ -648,11 +648,11 @@ function CreateMeshCentralServer(config, args) {
|
|||
if (typeof obj.args.trustedproxy == 'string') { obj.args.trustedproxy = obj.args.trustedproxy.split(' ').join('').split(','); }
|
||||
if (typeof obj.args.tlsoffload == 'string') { obj.args.tlsoffload = obj.args.tlsoffload.split(' ').join('').split(','); }
|
||||
|
||||
// Check if WebSocket compression is supported. It's broken in NodeJS v11.11 to v12.15
|
||||
// Check if WebSocket compression is supported. It's known to be broken in NodeJS v11.11 to v12.15, and v13.2
|
||||
const verSplit = process.version.substring(1).split('.');
|
||||
var ver = parseInt(verSplit[0]) + (parseInt(verSplit[1]) / 100);
|
||||
if ((ver >= 11.11) && (ver <= 12.15)) {
|
||||
if ((obj.args.wscompression === true) || (obj.args.agentwscompression === true)) { addServerWarning('WebSocket compression is disabled, this feature is broken in NodeJS v11.11 to v12.15.'); }
|
||||
if (((ver >= 11.11) && (ver <= 12.15)) || (ver == 13.2)) {
|
||||
if ((obj.args.wscompression === true) || (obj.args.agentwscompression === true)) { addServerWarning('WebSocket compression is disabled, this feature is broken in NodeJS v11.11 to v12.15 and v13.2'); }
|
||||
obj.args.wscompression = obj.args.agentwscompression = false;
|
||||
obj.config.settings.wscompression = obj.config.settings.agentwscompression = false;
|
||||
}
|
||||
|
@ -2708,7 +2708,7 @@ function mainStart() {
|
|||
// Setup encrypted zip support if needed
|
||||
if (config.settings.autobackup && config.settings.autobackup.zippassword) {
|
||||
modules.push('archiver-zip-encrypted');
|
||||
if (config.settings.autobackup.googledrive == true) { if (nodeVersion >= 8) { modules.push('googleapis'); } else { config.settings.autobackup.googledrive = false; } } // Enable Google Drive Support
|
||||
if (typeof config.settings.autobackup.googledrive == 'object') { if (nodeVersion >= 8) { modules.push('googleapis'); } else { delete config.settings.autobackup.googledrive; } } // Enable Google Drive Support
|
||||
}
|
||||
|
||||
// Setup common password blocking
|
||||
|
|
16
meshuser.js
16
meshuser.js
|
@ -446,7 +446,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
}
|
||||
|
||||
// If we are site administrator and Google Drive backup is setup, send out the status.
|
||||
if ((user.siteadmin === SITERIGHT_ADMIN) && (domain.id == '') && (typeof parent.parent.config.settings.autobackup == 'object') && (parent.parent.config.settings.autobackup.googledrive == true)) {
|
||||
if ((user.siteadmin === SITERIGHT_ADMIN) && (domain.id == '') && (typeof parent.parent.config.settings.autobackup == 'object') && (typeof parent.parent.config.settings.autobackup.googledrive == 'object')) {
|
||||
db.Get('GoogleDriveBackup', function (err, docs) {
|
||||
if (err != null) return;
|
||||
if (docs.length == 0) { try { ws.send(JSON.stringify({ action: 'serverBackup', service: 'googleDrive', state: 1 })); } catch (ex) { } }
|
||||
|
@ -4671,7 +4671,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
break;
|
||||
}
|
||||
case 'serverBackup': {
|
||||
if (user.siteadmin != SITERIGHT_ADMIN) return;
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (typeof parent.parent.config.settings.autobackup.googledrive != 'object')) return;
|
||||
if (command.service == 'googleDrive') {
|
||||
if (command.state == 0) {
|
||||
parent.db.Remove('GoogleDriveBackup', function () { try { ws.send(JSON.stringify({ action: 'serverBackup', service: 'googleDrive', state: 1 })); } catch (ex) { } });
|
||||
|
@ -4680,17 +4680,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
obj.oAuth2Client = new google.auth.OAuth2(command.clientid, command.clientsecret, "urn:ietf:wg:oauth:2.0:oob");
|
||||
obj.oAuth2Client.xxclientid = command.clientid;
|
||||
obj.oAuth2Client.xxclientsecret = command.clientsecret;
|
||||
//const authUrl = obj.oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: ['https://www.googleapis.com/auth/drive.file'] });
|
||||
const authUrl = obj.oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.appdata', 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive.metadata', 'https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/drive.photos.readonly', 'https://www.googleapis.com/auth/drive.readonly', 'https://www.googleapis.com/auth/drive.scripts'] });
|
||||
const authUrl = obj.oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: ['https://www.googleapis.com/auth/drive.file'] });
|
||||
try { ws.send(JSON.stringify({ action: 'serverBackup', service: 'googleDrive', state: 2, url: authUrl })); } catch (ex) { }
|
||||
} else if ((command.state == 2) && (obj.oAuth2Client != null)) {
|
||||
obj.oAuth2Client.getToken(command.code, function (err, token) {
|
||||
if (err != null) {
|
||||
console.log('getToken', err);
|
||||
} else {
|
||||
parent.db.Set({ _id: 'GoogleDriveBackup', state: 3, clientid: obj.oAuth2Client.xxclientid, clientsecret: obj.oAuth2Client.xxclientsecret, token: token });
|
||||
try { ws.send(JSON.stringify({ action: 'serverBackup', service: 'googleDrive', state: 3 })); } catch (ex) { }
|
||||
}
|
||||
if (err != null) { console.log('GoogleDrive (getToken) error: ', err); return; }
|
||||
parent.db.Set({ _id: 'GoogleDriveBackup', state: 3, clientid: obj.oAuth2Client.xxclientid, clientsecret: obj.oAuth2Client.xxclientsecret, token: token });
|
||||
try { ws.send(JSON.stringify({ action: 'serverBackup', service: 'googleDrive', state: 3 })); } catch (ex) { }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -88,7 +88,11 @@
|
|||
"backupIntervalHours": 24,
|
||||
"keepLastDaysBackup": 10,
|
||||
"zipPassword": "MyReallySecretPassword3",
|
||||
"_backupPath": "C:\\backups"
|
||||
"_backupPath": "C:\\backups",
|
||||
"_googleDrive": {
|
||||
"folderName": "MeshCentral-Backups",
|
||||
"maxFiles": 10
|
||||
}
|
||||
},
|
||||
"_redirects": {
|
||||
"meshcommander": "https://www.meshcommander.com/"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -461,7 +461,7 @@
|
|||
<div style="margin-left:25px">
|
||||
<div id="p2ServerActionsBackup"><div class="p2AccountActions"><span style="display:none"><strong>✓</strong></span></div><a href="{{{domainurl}}}backup.zip" rel="noreferrer noopener" target="_blank">Download server backup</a></div>
|
||||
<div id="p2ServerActionsRestore"><div class="p2AccountActions"><span style="display:none"><strong>✓</strong></span></div><a href=# onclick="return server_showRestoreDlg()">Restore server with backup</a></div>
|
||||
<div id="p2ServerActionsGoogleBackup"><div class="p2AccountActions"><span id="p2ServerActionsGoogleBackupCheck" style="display:none"><strong>✓</strong></span></div><span><a href=# onclick="return server_setupGoogleDriveBackup()">Google Drive backup</a><br /></span></div>
|
||||
<div id="p2ServerActionsGoogleBackup" style="display:none"><div class="p2AccountActions"><span id="p2ServerActionsGoogleBackupCheck" style="display:none"><strong>✓</strong></span></div><span><a href=# onclick="return server_setupGoogleDriveBackup()">Google Drive backup</a><br /></span></div>
|
||||
<div id="p2ServerActionsVersion"><div class="p2AccountActions"><span style="display:none"><strong>✓</strong></span></div><a href=# onclick="return server_showVersionDlg()">Check server version</a></div>
|
||||
<div id="p2ServerActionsErrors"><div class="p2AccountActions"><span style="display:none"><strong>✓</strong></span></div><a href=# onclick="return server_showErrorsDlg()">Show server error log</a></div>
|
||||
</div>
|
||||
|
@ -3056,11 +3056,12 @@
|
|||
QV('p2ServerActionsGoogleBackupCheck', message.state > 2);
|
||||
miscState['googleDrive'] = { state: message.state }
|
||||
if (message.state == 2) {
|
||||
var x = "Nagivate to the URL below, grant access and copy the token code back." + '<br /><br />';
|
||||
var x = '<img style=float:right src="images/googledrive-48.png" /><div>' + "Nagivate to the URL below, grant access and copy the token code back." + '</div><br />';
|
||||
x += addHtmlValue("Activation", '<a href=\"' + message.url + '\" rel="noreferrer noopener" target="_blank">Browse to this URL</a>');
|
||||
x += addHtmlValue("Code", '<input id=gdcode style=width:240px></input>');
|
||||
setDialogMode(2, "Google Drive Backup", 1, server_setupGoogleDriveBackupEx, x, 'gd2');
|
||||
x += addHtmlValue("Code", '<input id=gdcode onkeyup=server_setupGoogleDriveBackupCheck3() style=width:240px></input>');
|
||||
setDialogMode(2, "Google Drive Backup", 3, server_setupGoogleDriveBackupEx, x, 'gd2');
|
||||
Q('gdcode').focus();
|
||||
QE('idx_dlgOkButton', false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -9139,21 +9140,25 @@
|
|||
function server_setupGoogleDriveBackup() {
|
||||
if (xxdialogMode || (miscState['googleDrive'] == null)) return false;
|
||||
var gd = miscState['googleDrive'];
|
||||
if (gd.state == 1) {
|
||||
var x = "You can setup MeshCentral to automatically send a server backup to Google Drive. Start by entering a desktop Google API ClientID and ClientSecret for your account." + '<br /><br />';
|
||||
x += addHtmlValue("Client ID", '<input id=gdclientid style=width:240px></input>');
|
||||
x += addHtmlValue("Client Secret", '<input id=gdclientsecret style=width:240px></input>');
|
||||
setDialogMode(2, "Google Drive Backup", 1, server_setupGoogleDriveBackupEx, x, 'gd1');
|
||||
if (gd.state < 3) {
|
||||
var x = '<img style=float:right src="images/googledrive-48.png" /><div>' + "Setup this server to automatically upload backups to Google Drive. Start by creating and entering a Google Drive ClientID and ClientSecret for your account." + '</div><br />';
|
||||
x += addHtmlValue("Credentials", '<a href="https://console.developers.google.com/apis/api/drive.googleapis.com/credentials" rel="noreferrer noopener" target="_blank">' + "Google Drive Console" + '</a>');
|
||||
x += addHtmlValue("Client ID", '<input id=gdclientid style=width:240px placeholder="xxxxxxxx.apps.googleusercontent.com" onkeyup=server_setupGoogleDriveBackupCheck1()></input>');
|
||||
x += addHtmlValue("Client Secret", '<input id=gdclientsecret style=width:240px onkeyup=server_setupGoogleDriveBackupCheck1()></input>');
|
||||
setDialogMode(2, "Google Drive Backup", 3, server_setupGoogleDriveBackupEx, x, 'gd1');
|
||||
Q('gdclientid').focus();
|
||||
QE('idx_dlgOkButton', false);
|
||||
} else if (gd.state == 3) {
|
||||
var x = "Google Drive backup is currently active.";
|
||||
x += '<br /><br /><label><input id=gdcheck type=checkbox onchange=server_setupGoogleDriveBackupCheck() />' + "Remove Configuration" + '</label>';
|
||||
var x = '<img style=float:right src="images/googledrive-48.png" /><div>' + "Google Drive backup is currently active." + '</div>';
|
||||
x += '<br /><label><input id=gdcheck type=checkbox onchange=server_setupGoogleDriveBackupCheck2() />' + "Remove Configuration" + '</label>';
|
||||
setDialogMode(2, "Google Drive Backup", 3, server_setupGoogleDriveBackupEx, x, 'gd0');
|
||||
QE('idx_dlgOkButton', false);
|
||||
}
|
||||
}
|
||||
|
||||
function server_setupGoogleDriveBackupCheck() { QE('idx_dlgOkButton', Q('gdcheck').checked); }
|
||||
function server_setupGoogleDriveBackupCheck1() { QE('idx_dlgOkButton', (Q('gdclientid').value.length > 0) && (Q('gdclientsecret').value.length > 0)); }
|
||||
function server_setupGoogleDriveBackupCheck2() { QE('idx_dlgOkButton', Q('gdcheck').checked); }
|
||||
function server_setupGoogleDriveBackupCheck3() { QE('idx_dlgOkButton', Q('gdcode').value.length > 0); }
|
||||
|
||||
function server_setupGoogleDriveBackupEx(b, t) {
|
||||
if (t == 'gd0') { meshserver.send({ action: 'serverBackup', service: 'googleDrive', state: 0 }); }
|
||||
|
@ -13055,11 +13060,11 @@
|
|||
if (installedPluginList['version_info'] != null && installedPluginList['version_info'][p._id] != null) {
|
||||
var vin = installedPluginList['version_info'][p._id];
|
||||
if (vin.hasUpdate) {
|
||||
p.upgradeAvail = '<a title="' + "View Changelog" + '" target="_blank" href="' + vin.changelogUrl + '">' + vin.version + '</a>';
|
||||
p.upgradeAvail = '<a title="' + "View Changelog" + '" rel="noreferrer noopener" target="_blank" href="' + vin.changelogUrl + '">' + vin.version + '</a>';
|
||||
} else {
|
||||
cant_action.push('upgrade');
|
||||
if (p.status) p.upgradeAvail = "Up to date";
|
||||
else p.upgradeAvail = '<a title="' + "View Changelog" + '" target="_blank" href="' + vin.changelogUrl + '">' + vin.version + '</a>';
|
||||
else p.upgradeAvail = '<a title="' + "View Changelog" + '" rel="noreferrer noopener" target="_blank" href="' + vin.changelogUrl + '">' + vin.version + '</a>';
|
||||
}
|
||||
if (!vin.meshCentralCompat) {
|
||||
p.upgradeAvail += vers_not_compat;
|
||||
|
@ -13077,7 +13082,7 @@
|
|||
}
|
||||
p.actions += '</select>';
|
||||
|
||||
var tpl = '<td><img style=margin-top:3px src=images/plugin24.png></td><td class=gradTable1> </td><td class=gradTable2>' + p.nameHtml + '</td><td class=gradTable2>' + EscapeHtml(p.description) + '</td><td class=gradTable2 style=text-align:center><a href="' + EscapeHtml(p.homepage) + '" target="_blank">Home</a></td><td class=gradTable2 style=text-align:center>' + EscapeHtml(p.version) + '</td><td style=text-align:center class="pluginUpgradeAvailable gradTable2">' + p.upgradeAvail + '</td><td class=gradTable2 style="text-align:center;color:#' + p.statusColor + '">' + p.statusText + '</td><td class="pluginAction gradTable2" style=text-align:center>' + p.actions + '</td><td class=gradTable3> </td>';
|
||||
var tpl = '<td><img style=margin-top:3px src=images/plugin24.png></td><td class=gradTable1> </td><td class=gradTable2>' + p.nameHtml + '</td><td class=gradTable2>' + EscapeHtml(p.description) + '</td><td class=gradTable2 style=text-align:center><a href="' + EscapeHtml(p.homepage) + '" rel="noreferrer noopener" target="_blank">Home</a></td><td class=gradTable2 style=text-align:center>' + EscapeHtml(p.version) + '</td><td style=text-align:center class="pluginUpgradeAvailable gradTable2">' + p.upgradeAvail + '</td><td class=gradTable2 style="text-align:center;color:#' + p.statusColor + '">' + p.statusText + '</td><td class="pluginAction gradTable2" style=text-align:center>' + p.actions + '</td><td class=gradTable3> </td>';
|
||||
var tr = tbl.insertRow(-1);
|
||||
tr.innerHTML = tpl;
|
||||
tr.classList.add('p42tblRow');
|
||||
|
|
|
@ -3758,9 +3758,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
ws.send('5'); // Indicate we want to perform file transfers (5 = Files).
|
||||
if (ws.xcmd == 'coredump') {
|
||||
// Check the agent core dump folder if not already present.
|
||||
var coreDumpPath = obj.path.join(parent.datapath, 'coredumps');
|
||||
var coreDumpPath = obj.path.join(parent.datapath, '..', 'meshcentral-coredumps');
|
||||
if (obj.fs.existsSync(coreDumpPath) == false) { try { obj.fs.mkdirSync(coreDumpPath); } catch (ex) { } }
|
||||
ws.xfilepath = obj.path.join(parent.datapath, 'coredumps', ws.xarg);
|
||||
ws.xfilepath = obj.path.join(parent.datapath, '..', 'meshcentral-coredumps', ws.xarg);
|
||||
ws.xid = 'coredump';
|
||||
ws.send(JSON.stringify({ action: 'download', sub: 'start', ask: 'coredump', id: 'coredump' })); // Ask for a directory (test)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue