Files
kopia/app/public/server.js
dependabot[bot] 6235ba5c6b build(deps): bump the kopia-ui-npm-dependencies group across 1 directory with 9 updates + upgraded 'app' to ESM modules (#3978)
* build(deps): bump the kopia-ui-npm-dependencies group across 1 directory with 9 updates

Bumps the kopia-ui-npm-dependencies group with 7 updates in the /app directory:

| Package | From | To |
| --- | --- | --- |
| [electron-log](https://github.com/megahertz/electron-log) | `5.1.2` | `5.1.5` |
| [electron-store](https://github.com/sindresorhus/electron-store) | `8.2.0` | `10.0.0` |
| [electron-updater](https://github.com/electron-userland/electron-builder/tree/HEAD/packages/electron-updater) | `6.3.0-alpha.6` | `6.3.0-alpha.7` |
| [uuid](https://github.com/uuidjs/uuid) | `9.0.1` | `10.0.0` |
| [@electron/notarize](https://github.com/electron/notarize) | `2.3.0` | `2.3.2` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.42.1` | `1.45.1` |
| [electron](https://github.com/electron/electron) | `29.1.6` | `31.2.0` |



Updates `electron-log` from 5.1.2 to 5.1.5
- [Changelog](https://github.com/megahertz/electron-log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/megahertz/electron-log/compare/v5.1.2...v5.1.5)

Updates `electron-store` from 8.2.0 to 10.0.0
- [Release notes](https://github.com/sindresorhus/electron-store/releases)
- [Commits](https://github.com/sindresorhus/electron-store/compare/v8.2.0...v10.0.0)

Updates `electron-updater` from 6.3.0-alpha.6 to 6.3.0-alpha.7
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/commits/electron-updater@6.3.0-alpha.7/packages/electron-updater)

Updates `uuid` from 9.0.1 to 10.0.0
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v9.0.1...v10.0.0)

Updates `@electron/notarize` from 2.3.0 to 2.3.2
- [Release notes](https://github.com/electron/notarize/releases)
- [Changelog](https://github.com/electron/notarize/blob/main/.releaserc.json)
- [Commits](https://github.com/electron/notarize/compare/v2.3.0...v2.3.2)

Updates `@playwright/test` from 1.42.1 to 1.45.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.42.1...v1.45.1)

Updates `electron` from 29.1.6 to 31.2.0
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v29.1.6...v31.2.0)

Updates `playwright` from 1.42.1 to 1.45.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.42.1...v1.45.1)

Updates `playwright-core` from 1.42.1 to 1.45.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.42.1...v1.45.1)

---
updated-dependencies:
- dependency-name: electron-log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: electron-store
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: electron-updater
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: "@electron/notarize"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: "@playwright/test"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: electron
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: playwright
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: kopia-ui-npm-dependencies
- dependency-name: playwright-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: kopia-ui-npm-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* upgraded app to ES modules

* renamed notarize.js and sign.js to CommonJS

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Kowalski <jaak@jkowalski.net>
2024-07-13 02:31:41 +00:00

256 lines
8.3 KiB
JavaScript

import { ipcMain } from 'electron';
const path = await import('path');
const https = await import('https');
import { defaultServerBinary } from './utils.js';
import { spawn } from 'child_process';
import log from "electron-log";
import { configDir, isPortableConfig } from './config.js';
let servers = {};
function newServerForRepo(repoID) {
let runningServerProcess = null;
let runningServerCertSHA256 = "";
let runningServerPassword = "";
let runningServerControlPassword = "";
let runningServerAddress = "";
let runningServerCertificate = "";
let runningServerStatusDetails = {
startingUp: true,
};
let serverLog = [];
const maxLogLines = 100;
return {
actuateServer() {
log.info('actuating Server', repoID);
this.stopServer();
this.startServer();
},
startServer() {
let kopiaPath = defaultServerBinary();
let args = [];
args.push('server', 'start', '--ui',
'--tls-print-server-cert',
'--tls-generate-cert-name=127.0.0.1',
'--random-password',
'--random-server-control-password',
'--tls-generate-cert',
'--async-repo-connect',
'--shutdown-on-stdin', // shutdown the server when parent dies
'--address=127.0.0.1:0');
args.push("--config-file", path.resolve(configDir(), repoID + ".config"));
if (isPortableConfig()) {
const cacheDir = path.resolve(configDir(), "cache", repoID);
const logsDir = path.resolve(configDir(), "logs", repoID);
args.push("--cache-directory", cacheDir);
args.push("--log-dir", logsDir);
}
log.info(`spawning ${kopiaPath} ${args.join(' ')}`);
runningServerProcess = spawn(kopiaPath, args, {
});
this.raiseStatusUpdatedEvent();
runningServerProcess.stdout.on('data', this.appendToLog.bind(this));
runningServerProcess.stderr.on('data', this.detectServerParam.bind(this));
const p = runningServerProcess;
log.info('starting polling loop');
const statusUpdated = this.raiseStatusUpdatedEvent.bind(this);
const pollInterval = 3000;
function pollOnce() {
if (!runningServerAddress || !runningServerCertificate || !runningServerPassword || !runningServerControlPassword) {
return;
}
const req = https.request({
ca: [runningServerCertificate],
host: "127.0.0.1",
port: parseInt(new URL(runningServerAddress).port),
method: "GET",
path: "/api/v1/control/status",
timeout: pollInterval,
headers: {
'Authorization': 'Basic ' + Buffer.from("server-control" + ':' + runningServerControlPassword).toString('base64')
}
}, (resp) => {
if (resp.statusCode === 200) {
resp.on('data', x => {
try {
const newDetails = JSON.parse(x);
if (JSON.stringify(newDetails) != JSON.stringify(runningServerStatusDetails)) {
runningServerStatusDetails = newDetails;
statusUpdated();
}
} catch (e) {
log.warn('unable to parse status JSON', e);
}
});
} else {
log.warn('error fetching status', resp.statusMessage);
}
});
req.on('error', (e)=>{
log.info('error fetching status', e);
});
req.end();
}
const statusPollInterval = setInterval(pollOnce, pollInterval);
runningServerProcess.on('close', (code, signal) => {
this.appendToLog(`child process exited with code ${code} and signal ${signal}`);
if (runningServerProcess === p) {
clearInterval(statusPollInterval);
runningServerAddress = "";
runningServerPassword = "";
runningServerControlPassword = "";
runningServerCertSHA256 = "";
runningServerProcess = null;
this.raiseStatusUpdatedEvent();
}
});
},
detectServerParam(data) {
let lines = (data + '').split('\n');
for (let i = 0; i < lines.length; i++) {
const p = lines[i].indexOf(": ");
if (p < 0) {
continue
}
const key = lines[i].substring(0, p);
const value = lines[i].substring(p + 2);
switch (key) {
case "SERVER PASSWORD":
runningServerPassword = value;
this.raiseStatusUpdatedEvent();
break;
case "SERVER CONTROL PASSWORD":
runningServerControlPassword = value;
this.raiseStatusUpdatedEvent();
break;
case "SERVER CERT SHA256":
runningServerCertSHA256 = value;
this.raiseStatusUpdatedEvent();
break;
case "SERVER CERTIFICATE":
runningServerCertificate = Buffer.from(value, 'base64').toString('ascii');
this.raiseStatusUpdatedEvent();
break;
case "SERVER ADDRESS":
runningServerAddress = value;
this.raiseStatusUpdatedEvent();
break;
}
}
this.appendToLog(data);
},
appendToLog(data) {
const l = serverLog.push(data);
if (l > maxLogLines) {
serverLog.splice(0, 1);
}
ipcMain.emit('logs-updated-event', {
repoID: repoID,
logs: serverLog.join(''),
});
log.info(`${data}`);
},
stopServer() {
if (!runningServerProcess) {
log.info('stopServer: server not started');
return;
}
runningServerProcess.kill();
runningServerAddress = "";
runningServerPassword = "";
runningServerCertSHA256 = "";
runningServerCertificate = "";
runningServerProcess = null;
this.raiseStatusUpdatedEvent();
},
getServerAddress() {
return runningServerAddress;
},
getServerCertSHA256() {
return runningServerCertSHA256;
},
getServerPassword() {
return runningServerPassword;
},
getServerStatusDetails() {
return runningServerStatusDetails;
},
getServerStatus() {
if (!runningServerProcess) {
return "Stopped";
}
if (runningServerCertSHA256 && runningServerAddress && runningServerPassword) {
return "Running";
}
return "Starting";
},
raiseStatusUpdatedEvent() {
const args = {
repoID: repoID,
status: this.getServerStatus(),
serverAddress: this.getServerAddress() || "<pending>",
serverCertSHA256: this.getServerCertSHA256() || "<pending>",
};
ipcMain.emit('status-updated-event', args);
},
};
};
ipcMain.on('status-fetch', (event, args) => {
const repoID = args.repoID;
const s = servers[repoID]
if (s) {
s.raiseStatusUpdatedEvent();
}
})
export function serverForRepo(repoID) {
let s = servers[repoID];
if (s) {
return s;
}
s = newServerForRepo(repoID);
servers[repoID] = s;
return s;
}