docker-client-mx 1.43.0 → 1.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docker-desktop-mx/browser/{chunk-BpQVP_gf.js → chunk-Af1e1d8G.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-D5njuWRz.js → chunk-B13W1gEu.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-B2NHI2Ew.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-k-zsJmvX.js → chunk-B3n-2UOi.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-BIIdmzaV2.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-BJACElSf2.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-BsTDUJ3m.js → chunk-BPNQPsl2.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-BUtOgCv_.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-BZwYBA7Z.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-Bcx5WMyJ.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-DLpC_2HL.js → chunk-Bd5-MqqR.js} +16 -16
- package/dist/docker-desktop-mx/browser/{chunk-xmDwFpQl.js → chunk-BxKOYZan.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-C7c_wFw-.js → chunk-BxU6JdzU.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-DS3iAefP.js → chunk-C3u9Hm0s.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-CGft6wQH2.js +6 -0
- package/dist/docker-desktop-mx/browser/chunk-CHa6bNlc.js +6 -0
- package/dist/docker-desktop-mx/browser/{chunk-CpNGhf9S.js → chunk-COBWzwhz.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-75uKIulV.js → chunk-COdMLD3H.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-CXpIB_qc.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-Bxte2YBm.js → chunk-ClGJowQ7.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-gHmeiJFn.js → chunk-Clfbc1-d.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-yYm_2q6C.js → chunk-CoprhnOm.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-CsQ_euXP.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-D2SM5E9h.js → chunk-D3bHzook.js} +3 -3
- package/dist/docker-desktop-mx/browser/chunk-DEXem6rk.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-DPn8Rpg4.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-DVXm8E_S.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-DX-Zo-hw.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-DZ-f89Uu.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-DZXhuKXm.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-CjAbzLl3.js → chunk-DctinxSO.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-DeXGJ-vD2.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-D86K3m6W.js → chunk-Dy_g3RHY.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-EFAsN7J4.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-FqKVK_Os2.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-VC5gaeEq.js → chunk-IMRsZUv82.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-U7tL4XEw2.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-YQkNtrRq.js +1 -0
- package/dist/docker-desktop-mx/browser/chunk-_wm6hEEA.js +1 -0
- package/dist/docker-desktop-mx/browser/{chunk-qxDOm16k.js → chunk-eVHlLrxe.js} +2 -2
- package/dist/docker-desktop-mx/browser/{chunk-B1xjyPnV.js → chunk-jpKpwesj.js} +1 -1
- package/dist/docker-desktop-mx/browser/{chunk-vPeKxmUB.js → chunk-m112xmv9.js} +1 -1
- package/dist/docker-desktop-mx/browser/chunk-u0OAgv4f.js +4 -0
- package/dist/docker-desktop-mx/browser/index.html +2 -2
- package/dist/docker-desktop-mx/browser/main-INZSNGJM.js +1 -0
- package/dist/docker-desktop-mx/browser/styles-BGYQU5CU.css +1 -0
- package/dist-electron/channels.js +8 -0
- package/dist-electron/channels.js.map +1 -1
- package/dist-electron/container-adjust.js +182 -0
- package/dist-electron/container-adjust.js.map +1 -0
- package/dist-electron/exec.js +78 -7
- package/dist-electron/exec.js.map +1 -1
- package/dist-electron/file-edit.js +206 -0
- package/dist-electron/file-edit.js.map +1 -0
- package/dist-electron/ipc.js +49 -12
- package/dist-electron/ipc.js.map +1 -1
- package/dist-electron/log-export.js +5 -4
- package/dist-electron/log-export.js.map +1 -1
- package/dist-electron/logs.js +26 -10
- package/dist-electron/logs.js.map +1 -1
- package/dist-electron/preload.js +20 -4
- package/dist-electron/preload.js.map +1 -1
- package/dist-electron/system.js +51 -1
- package/dist-electron/system.js.map +1 -1
- package/dist-electron/volume-file-edit.js +78 -0
- package/dist-electron/volume-file-edit.js.map +1 -0
- package/dist-electron/volume-files.js +8 -6
- package/dist-electron/volume-files.js.map +1 -1
- package/package.json +1 -1
- package/dist/docker-desktop-mx/browser/chunk-B-8njY4y.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-BE5ctn7s.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-BNz89YmT2.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-BYBsnx9-2.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-CUSsr_nJ.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-CaR7Z77S2.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-Cau4mGeC.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-CjySsWe4.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-CpIMiI_l.js +0 -4
- package/dist/docker-desktop-mx/browser/chunk-CphQt55R.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-Cpz4zP5G.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-Cx-uRg2m.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-DCYTwazU.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-DGnxa3ti2.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-DNfiG-TG.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-DdTfHpyK.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-DnY7-enP.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-Q3Ig-PJ6.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-hJqozYgS.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-hXmaVpBu2.js +0 -1
- package/dist/docker-desktop-mx/browser/chunk-iWbUoQd52.js +0 -6
- package/dist/docker-desktop-mx/browser/chunk-sxrgZH0E.js +0 -3
- package/dist/docker-desktop-mx/browser/main-UUO74KHR.js +0 -1
- package/dist/docker-desktop-mx/browser/styles-IM2TO7ZD.css +0 -1
package/dist-electron/exec.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXEC_USER = exports.STOP_SCRIPT = void 0;
|
|
4
|
+
exports.terminalMark = terminalMark;
|
|
3
5
|
exports.wrapSession = wrapSession;
|
|
4
6
|
exports.openExec = openExec;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
8
|
const docker_client_1 = require("./docker-client");
|
|
6
9
|
const i18n_1 = require("./i18n");
|
|
7
10
|
/**
|
|
@@ -12,6 +15,31 @@ const i18n_1 = require("./i18n");
|
|
|
12
15
|
* vragen het eerst. Dat kost één korte exec, en het antwoord is eenduidig.
|
|
13
16
|
*/
|
|
14
17
|
const PROBE = 'for c in /bin/bash /usr/bin/bash /bin/sh /usr/bin/sh /bin/ash; do [ -x "$c" ] && echo "$c" && exit 0; done; exit 1';
|
|
18
|
+
/**
|
|
19
|
+
* Ruimt de processen van één terminal op (fase 79): alles met dit kenmerk in de omgeving, dus de
|
|
20
|
+
* shell en wat erin gestart is. Eerst SIGHUP, zoals een terminal die ophangt; wat na een seconde nog
|
|
21
|
+
* leeft, SIGKILL. `$1` is het kenmerk; het script zelf heeft het niet in zijn omgeving.
|
|
22
|
+
*/
|
|
23
|
+
exports.STOP_SCRIPT = [
|
|
24
|
+
'm="MX_TERMINAL=$1"',
|
|
25
|
+
'hit() { for p in /proc/[0-9]*; do tr \'\\000\' \'\\n\' < "$p/environ" 2>/dev/null | grep -qx "$m" && echo "${p#/proc/}"; done; }',
|
|
26
|
+
'pids=$(hit); [ -z "$pids" ] && exit 0',
|
|
27
|
+
'kill -HUP $pids 2>/dev/null; sleep 1',
|
|
28
|
+
'pids=$(hit); [ -n "$pids" ] && kill -KILL $pids 2>/dev/null; exit 0',
|
|
29
|
+
].join('\n');
|
|
30
|
+
/** Het kenmerk dat een terminal meekrijgt: zo vindt het opruimen precies zijn eigen processen terug. */
|
|
31
|
+
function terminalMark() {
|
|
32
|
+
return (0, node_crypto_1.randomUUID)();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Wat Docker als gebruiker van een exec aanneemt: een naam of een uid, eventueel met `:groep`.
|
|
36
|
+
* Strenger dan nodig, zodat er nooit iets anders in de API-aanroep terechtkomt.
|
|
37
|
+
*/
|
|
38
|
+
exports.EXEC_USER = /^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,31}(:[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,31})?$/;
|
|
39
|
+
/** Alleen meegeven als er een gebruiker gekozen is; zonder `User` neemt Docker die van de image. */
|
|
40
|
+
function asUser(user) {
|
|
41
|
+
return user === null ? {} : { User: user };
|
|
42
|
+
}
|
|
15
43
|
/** Leest de uitvoer van een korte exec uit; de shell-probe schrijft één regel. */
|
|
16
44
|
function readAll(stream) {
|
|
17
45
|
return new Promise((resolve) => {
|
|
@@ -22,10 +50,12 @@ function readAll(stream) {
|
|
|
22
50
|
});
|
|
23
51
|
}
|
|
24
52
|
const dockerBackend = {
|
|
25
|
-
detectShell: async (containerId) => {
|
|
53
|
+
detectShell: async (containerId, user) => {
|
|
26
54
|
const { docker } = (0, docker_client_1.getConnection)();
|
|
27
55
|
try {
|
|
56
|
+
// Als dezelfde gebruiker als de shell straks: een naam die er niet is, valt dan hier al op.
|
|
28
57
|
const probe = await docker.getContainer(containerId).exec({
|
|
58
|
+
...asUser(user),
|
|
29
59
|
Cmd: ['/bin/sh', '-c', PROBE],
|
|
30
60
|
AttachStdout: true,
|
|
31
61
|
AttachStderr: false,
|
|
@@ -40,15 +70,18 @@ const dockerBackend = {
|
|
|
40
70
|
return null;
|
|
41
71
|
}
|
|
42
72
|
},
|
|
43
|
-
start: async (containerId, shell, size) => {
|
|
73
|
+
start: async (containerId, shell, size, user) => {
|
|
44
74
|
const { docker } = (0, docker_client_1.getConnection)();
|
|
75
|
+
const mark = terminalMark();
|
|
45
76
|
const exec = await docker.getContainer(containerId).exec({
|
|
77
|
+
...asUser(user),
|
|
46
78
|
Cmd: [shell],
|
|
47
79
|
AttachStdin: true,
|
|
48
80
|
AttachStdout: true,
|
|
49
81
|
AttachStderr: true,
|
|
50
82
|
Tty: true,
|
|
51
|
-
|
|
83
|
+
// Het kenmerk erven ook de programma's die je in de shell start; zie STOP_SCRIPT.
|
|
84
|
+
Env: ['TERM=xterm-256color', `MX_TERMINAL=${mark}`],
|
|
52
85
|
});
|
|
53
86
|
// Drie dingen moeten hier staan, en het derde is een valkuil:
|
|
54
87
|
// - hijack maakt van de HTTP-verbinding een tweerichtingskanaal in plaats van een antwoord;
|
|
@@ -65,15 +98,35 @@ const dockerBackend = {
|
|
|
65
98
|
// Een resize op een exec die net gestopt is geeft een 404; dat is geen fout om te melden.
|
|
66
99
|
void exec.resize({ h: rows, w: cols }).catch(() => undefined);
|
|
67
100
|
},
|
|
101
|
+
// Met een TTY hangt Docker de terminal niet op als de verbinding sluit: de shell bleef dan
|
|
102
|
+
// draaien, ook als root (fase 79). Dus zelf opruimen, als dezelfde gebruiker.
|
|
103
|
+
stop: () => void stopTerminal(containerId, mark, user),
|
|
68
104
|
};
|
|
69
105
|
},
|
|
70
106
|
};
|
|
107
|
+
/** Draait STOP_SCRIPT in de container. Lukt het niet (container al weg), dan is er ook niets meer op te ruimen. */
|
|
108
|
+
async function stopTerminal(containerId, mark, user) {
|
|
109
|
+
try {
|
|
110
|
+
const exec = await (0, docker_client_1.getConnection)().docker.getContainer(containerId).exec({
|
|
111
|
+
...asUser(user),
|
|
112
|
+
Cmd: ['/bin/sh', '-c', exports.STOP_SCRIPT, 'mx', mark],
|
|
113
|
+
AttachStdout: true,
|
|
114
|
+
AttachStderr: true,
|
|
115
|
+
});
|
|
116
|
+
const stream = await exec.start({ hijack: true, stdin: false });
|
|
117
|
+
await readAll(stream);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Niets aan te doen, en niets om te melden: de terminal is al dicht.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
71
123
|
/**
|
|
72
124
|
* Maakt van een ruwe TTY-stream een sessie. `stop` ruimt op wat er naast de stream nog draait,
|
|
73
125
|
* zoals de hulpcontainer van de host-shell.
|
|
74
126
|
*/
|
|
75
127
|
function wrapSession(shell, stream, resize, onData, onEnd, stop = () => undefined) {
|
|
76
128
|
let closed = false;
|
|
129
|
+
let destroyed = false;
|
|
77
130
|
const finish = () => {
|
|
78
131
|
if (!closed) {
|
|
79
132
|
closed = true;
|
|
@@ -93,6 +146,11 @@ function wrapSession(shell, stream, resize, onData, onEnd, stop = () => undefine
|
|
|
93
146
|
},
|
|
94
147
|
resize,
|
|
95
148
|
destroy: () => {
|
|
149
|
+
// Sluiten kan van twee kanten komen (de tab en het venster); opruimen hoeft maar één keer.
|
|
150
|
+
if (destroyed) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
destroyed = true;
|
|
96
154
|
closed = true;
|
|
97
155
|
stream.destroy();
|
|
98
156
|
stop();
|
|
@@ -106,8 +164,21 @@ function wrapSession(shell, stream, resize, onData, onEnd, stop = () => undefine
|
|
|
106
164
|
* inclusief de escape-codes, want díé zijn hier juist de bedoeling. Dat is het verschil met de
|
|
107
165
|
* logweergave, waar we ze er juist uit halen.
|
|
108
166
|
*/
|
|
109
|
-
async function openExec(containerId, size, onData, onEnd, backend = dockerBackend) {
|
|
110
|
-
const shell = await backend.detectShell(containerId);
|
|
167
|
+
async function openExec(containerId, size, onData, onEnd, backend = dockerBackend, user = null) {
|
|
168
|
+
const shell = await backend.detectShell(containerId, user);
|
|
169
|
+
// Met een gekozen gebruiker is "geen shell" meestal "geen gebruiker met die naam".
|
|
170
|
+
if (shell === null && user !== null) {
|
|
171
|
+
return {
|
|
172
|
+
ok: false,
|
|
173
|
+
problem: (0, i18n_1.t)({
|
|
174
|
+
en: `No shell could be started as ${user}. Does that user exist in this container?`,
|
|
175
|
+
nl: `Als ${user} kon geen shell gestart worden. Bestaat die gebruiker in deze container?`,
|
|
176
|
+
de: `Als ${user} konnte keine Shell gestartet werden. Gibt es diesen Benutzer in diesem Container?`,
|
|
177
|
+
fr: `Aucun shell n’a pu être démarré en tant que ${user}. Cet utilisateur existe-t-il dans ce conteneur ?`,
|
|
178
|
+
es: `No se ha podido iniciar un shell como ${user}. ¿Existe ese usuario en este contenedor?`,
|
|
179
|
+
}),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
111
182
|
if (shell === null) {
|
|
112
183
|
return {
|
|
113
184
|
ok: false,
|
|
@@ -121,8 +192,8 @@ async function openExec(containerId, size, onData, onEnd, backend = dockerBacken
|
|
|
121
192
|
};
|
|
122
193
|
}
|
|
123
194
|
try {
|
|
124
|
-
const { stream, resize } = await backend.start(containerId, shell, size);
|
|
125
|
-
return { ok: true, session: wrapSession(shell, stream, resize, onData, onEnd) };
|
|
195
|
+
const { stream, resize, stop } = await backend.start(containerId, shell, size, user);
|
|
196
|
+
return { ok: true, session: wrapSession(shell, stream, resize, onData, onEnd, stop) };
|
|
126
197
|
}
|
|
127
198
|
catch (err) {
|
|
128
199
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../electron/exec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../electron/exec.ts"],"names":[],"mappings":";;;AAsDA,oCAGC;AA8GD,kCA4CC;AAaD,4BAqDC;AArRD,6CAAyC;AAEzC,mDAAgD;AAEhD,iCAA2B;AAE3B;;;;;;GAMG;AACH,MAAM,KAAK,GAAG,oHAAoH,CAAC;AA2BnI;;;;GAIG;AACU,QAAA,WAAW,GAAG;IACzB,oBAAoB;IACpB,kIAAkI;IAClI,uCAAuC;IACvC,sCAAsC;IACtC,qEAAqE;CACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,wGAAwG;AACxG,SAAgB,YAAY;IAE1B,OAAO,IAAA,wBAAU,GAAE,CAAC;AACtB,CAAC;AAED;;;GAGG;AACU,QAAA,SAAS,GAAG,wEAAwE,CAAC;AAElG,oGAAoG;AACpG,SAAS,MAAM,CAAC,IAAmB;IAEjC,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,kFAAkF;AAClF,SAAS,OAAO,CAAC,MAAc;IAE7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,aAAa,GAAgB;IACjC,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,6BAAa,GAAE,CAAC;QAEnC,IAAI,CAAC;YACH,4FAA4F;YAC5F,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;gBACxD,GAAG,MAAM,CAAC,IAAI,CAAC;gBACf,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC;gBAC7B,YAAY,EAAE,IAAI;gBAClB,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACjE,sFAAsF;YACtF,+EAA+E;YAC/E,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAExE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,6BAAa,GAAE,CAAC;QACnC,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;YACvD,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,GAAG,EAAE,CAAC,KAAK,CAAC;YACZ,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,GAAG,EAAE,IAAI;YACT,kFAAkF;YAClF,GAAG,EAAE,CAAC,qBAAqB,EAAE,eAAe,IAAI,EAAE,CAAC;SACpD,CAAC,CAAC;QAEH,8DAA8D;QAC9D,4FAA4F;QAC5F,yEAAyE;QACzE,4FAA4F;QAC5F,0FAA0F;QAC1F,mFAAmF;QACnF,0EAA0E;QAC1E,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAA6B,CAAC;QAExG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAElD,OAAO;YACL,MAAM;YACN,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;gBACrB,0FAA0F;gBAC1F,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAChE,CAAC;YACD,2FAA2F;YAC3F,8EAA8E;YAC9E,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,YAAY,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC;SACvD,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,mHAAmH;AACnH,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,IAAY,EAAE,IAAmB;IAEhF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAA,6BAAa,GAAE,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;YACvE,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,mBAAW,EAAE,IAAI,EAAE,IAAI,CAAC;YAC/C,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CACzB,KAAa,EACb,MAAqB,EACrB,MAA4C,EAC5C,MAA+B,EAC/B,KAAiB,EACjB,OAAmB,GAAG,EAAE,CAAC,SAAS;IAGlC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,IAAI,CAAC;YACd,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE3B,OAAO;QACL,KAAK;QACL,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QACD,MAAM;QACN,OAAO,EAAE,GAAG,EAAE;YACZ,2FAA2F;YAC3F,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YAED,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,GAAG,IAAI,CAAC;YACd,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,EAAE,CAAC;QACT,CAAC;KACF,CAAC;AACJ,CAAC;AAMD;;;;;;GAMG;AACI,KAAK,UAAU,QAAQ,CAC5B,WAAmB,EACnB,IAAoC,EACpC,MAA+B,EAC/B,KAAiB,EACjB,UAAuB,aAAa,EACpC,OAAsB,IAAI;IAG1B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAE3D,mFAAmF;IACnF,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAA,QAAC,EAAC;gBACT,EAAE,EAAE,gCAAgC,IAAI,2CAA2C;gBACnF,EAAE,EAAE,OAAO,IAAI,0EAA0E;gBACzF,EAAE,EAAE,OAAO,IAAI,oFAAoF;gBACnG,EAAE,EAAE,+CAA+C,IAAI,mDAAmD;gBAC1G,EAAE,EAAE,yCAAyC,IAAI,2CAA2C;aAC7F,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAA,QAAC,EAAC;gBACT,EAAE,EAAE,0FAA0F;gBAC9F,EAAE,EAAE,2FAA2F;gBAC/F,EAAE,EAAE,4FAA4F;gBAChG,EAAE,EAAE,mGAAmG;gBACvG,EAAE,EAAE,qGAAqG;aAC1G,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAErF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;IACxF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEhE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAA,QAAC,EAAC;gBAC7B,EAAE,EAAE,mCAAmC,MAAM,EAAE;gBAC/C,EAAE,EAAE,qCAAqC,MAAM,EAAE;gBACjD,EAAE,EAAE,4CAA4C,MAAM,EAAE;gBACxD,EAAE,EAAE,sCAAsC,MAAM,EAAE;gBAClD,EAAE,EAAE,qCAAqC,MAAM,EAAE;aAClD,CAAC,EAAE,CAAC;IACP,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MAX_EDIT_BYTES = void 0;
|
|
37
|
+
exports.asText = asText;
|
|
38
|
+
exports.versionOf = versionOf;
|
|
39
|
+
exports.onMount = onMount;
|
|
40
|
+
exports.readEditableFile = readEditableFile;
|
|
41
|
+
exports.saveEditableFile = saveEditableFile;
|
|
42
|
+
const node_crypto_1 = require("node:crypto");
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
const tar = __importStar(require("tar-stream"));
|
|
45
|
+
const docker_client_1 = require("./docker-client");
|
|
46
|
+
const files_1 = require("./files");
|
|
47
|
+
const i18n_1 = require("./i18n");
|
|
48
|
+
/**
|
|
49
|
+
* Een tekstbestand in een container bewerken (fase 78): lezen, en terugzetten met dezelfde rechten
|
|
50
|
+
* en eigenaar. Via `getArchive` en `putArchive`, zonder shell, zoals downloaden en uploaden.
|
|
51
|
+
*
|
|
52
|
+
* Alleen tekst en alleen klein: een editor in de app is voor een configuratieregel, niet voor een
|
|
53
|
+
* logbestand van honderd megabyte. De versie is een hash van de inhoud; opslaan leest eerst opnieuw
|
|
54
|
+
* en weigert als het bestand intussen veranderd is, in plaats van het stil te overschrijven.
|
|
55
|
+
*/
|
|
56
|
+
/** Groter dan dit is geen bestand om in de app te bewerken; dan blijven downloaden en uploaden. */
|
|
57
|
+
exports.MAX_EDIT_BYTES = 512 * 1024;
|
|
58
|
+
const MAX_LINK_HOPS = 8;
|
|
59
|
+
/** De eerste entry van een archief; de inhoud alleen als het een bestand is dat klein genoeg is. */
|
|
60
|
+
async function firstEntry(archive) {
|
|
61
|
+
const extract = tar.extract();
|
|
62
|
+
let found = null;
|
|
63
|
+
archive.pipe(extract);
|
|
64
|
+
for await (const entry of extract) {
|
|
65
|
+
const header = entry.header;
|
|
66
|
+
if (found === null) {
|
|
67
|
+
const small = header.type === 'file' && (header.size ?? 0) <= exports.MAX_EDIT_BYTES;
|
|
68
|
+
const chunks = [];
|
|
69
|
+
if (small) {
|
|
70
|
+
for await (const chunk of entry) {
|
|
71
|
+
chunks.push(chunk);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
entry.resume();
|
|
76
|
+
}
|
|
77
|
+
found = {
|
|
78
|
+
type: header.type ?? 'file',
|
|
79
|
+
size: header.size ?? 0,
|
|
80
|
+
mode: header.mode ?? 0o644,
|
|
81
|
+
uid: header.uid ?? 0,
|
|
82
|
+
gid: header.gid ?? 0,
|
|
83
|
+
linkname: header.linkname ?? null,
|
|
84
|
+
content: small ? Buffer.concat(chunks) : null,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
entry.resume();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return found;
|
|
92
|
+
}
|
|
93
|
+
/** Of dit tekst is die we heel terugschrijven: geen nul-bytes, en UTF-8 dat heen en terug gelijk blijft. */
|
|
94
|
+
function asText(content) {
|
|
95
|
+
if (content.includes(0)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const text = content.toString('utf8');
|
|
99
|
+
return Buffer.from(text, 'utf8').equals(content) ? text : null;
|
|
100
|
+
}
|
|
101
|
+
/** De versie van een bestand: een hash van de inhoud, om bij opslaan te zien of het veranderde. */
|
|
102
|
+
function versionOf(content) {
|
|
103
|
+
return (0, node_crypto_1.createHash)('sha256').update(content).digest('hex');
|
|
104
|
+
}
|
|
105
|
+
/** Of een pad onder een volume of bind mount valt; dan blijft een wijziging na "Opnieuw" staan. */
|
|
106
|
+
function onMount(file, destinations) {
|
|
107
|
+
return destinations.some((destination) => file === destination || file.startsWith(`${destination.replace(/\/$/, '')}/`));
|
|
108
|
+
}
|
|
109
|
+
/** Leest het bestand, en volgt een symlink zoals de container dat zou doen. */
|
|
110
|
+
async function read(id, requested) {
|
|
111
|
+
const container = (0, docker_client_1.getConnection)().docker.getContainer(id);
|
|
112
|
+
let current = (0, files_1.normalizeContainerPath)(requested);
|
|
113
|
+
for (let hop = 0; hop <= MAX_LINK_HOPS; hop += 1) {
|
|
114
|
+
const entry = await firstEntry((await container.getArchive({ path: current })));
|
|
115
|
+
if (entry?.type === 'symlink' && entry.linkname !== null) {
|
|
116
|
+
current = path.posix.resolve(path.posix.dirname(current), entry.linkname);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (entry === null || entry.type !== 'file') {
|
|
120
|
+
return { ok: false, problem: (0, i18n_1.t)({
|
|
121
|
+
en: `${current} is not a file.`,
|
|
122
|
+
nl: `${current} is geen bestand.`,
|
|
123
|
+
de: `${current} ist keine Datei.`,
|
|
124
|
+
fr: `${current} n’est pas un fichier.`,
|
|
125
|
+
es: `${current} no es un archivo.`,
|
|
126
|
+
}) };
|
|
127
|
+
}
|
|
128
|
+
return { ok: true, path: current, entry };
|
|
129
|
+
}
|
|
130
|
+
return { ok: false, problem: (0, i18n_1.t)({
|
|
131
|
+
en: `too many symlinks in a row from ${requested}.`,
|
|
132
|
+
nl: `te veel symlinks achter elkaar vanaf ${requested}.`,
|
|
133
|
+
de: `zu viele Symlinks hintereinander ab ${requested}.`,
|
|
134
|
+
fr: `trop de liens symboliques à la suite depuis ${requested}.`,
|
|
135
|
+
es: `demasiados symlinks seguidos desde ${requested}.`,
|
|
136
|
+
}) };
|
|
137
|
+
}
|
|
138
|
+
/** Leest een tekstbestand om te bewerken, met de versie om bij opslaan tegen te controleren. */
|
|
139
|
+
async function readEditableFile(id, requested) {
|
|
140
|
+
try {
|
|
141
|
+
const result = await read(id, requested);
|
|
142
|
+
if (!result.ok) {
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
const { entry } = result;
|
|
146
|
+
if (entry.content === null) {
|
|
147
|
+
return { ok: false, problem: (0, i18n_1.t)({
|
|
148
|
+
en: `${result.path} is larger than ${String(exports.MAX_EDIT_BYTES / 1024)} kB; download it to edit it.`,
|
|
149
|
+
nl: `${result.path} is groter dan ${String(exports.MAX_EDIT_BYTES / 1024)} kB; download het om het te bewerken.`,
|
|
150
|
+
de: `${result.path} ist größer als ${String(exports.MAX_EDIT_BYTES / 1024)} kB; laden Sie es zum Bearbeiten herunter.`,
|
|
151
|
+
fr: `${result.path} dépasse ${String(exports.MAX_EDIT_BYTES / 1024)} ko ; téléchargez-le pour le modifier.`,
|
|
152
|
+
es: `${result.path} supera los ${String(exports.MAX_EDIT_BYTES / 1024)} kB; descárgalo para editarlo.`,
|
|
153
|
+
}) };
|
|
154
|
+
}
|
|
155
|
+
const text = asText(entry.content);
|
|
156
|
+
if (text === null) {
|
|
157
|
+
return { ok: false, problem: (0, i18n_1.t)({
|
|
158
|
+
en: `${result.path} is not text (or not UTF-8); download it to edit it.`,
|
|
159
|
+
nl: `${result.path} is geen tekst (of geen UTF-8); download het om het te bewerken.`,
|
|
160
|
+
de: `${result.path} ist kein Text (oder kein UTF-8); laden Sie es zum Bearbeiten herunter.`,
|
|
161
|
+
fr: `${result.path} n’est pas du texte (ou pas en UTF-8) ; téléchargez-le pour le modifier.`,
|
|
162
|
+
es: `${result.path} no es texto (o no es UTF-8); descárgalo para editarlo.`,
|
|
163
|
+
}) };
|
|
164
|
+
}
|
|
165
|
+
const inspect = (await (0, docker_client_1.getConnection)().docker.getContainer(id).inspect());
|
|
166
|
+
const destinations = (inspect.Mounts ?? []).map((mount) => mount.Destination ?? '').filter((destination) => destination !== '');
|
|
167
|
+
return { ok: true, path: result.path, text, version: versionOf(entry.content), onMount: onMount(result.path, destinations) };
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
return { ok: false, problem: (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Zet de tekst terug, met de rechten, eigenaar en groep die het bestand had. Is het intussen
|
|
175
|
+
* veranderd (een andere versie dan `version`), dan niet: `conflict` zegt dat, tenzij `force`.
|
|
176
|
+
*/
|
|
177
|
+
async function saveEditableFile(id, file, text, version, force) {
|
|
178
|
+
try {
|
|
179
|
+
const current = await read(id, file);
|
|
180
|
+
if (!current.ok) {
|
|
181
|
+
return { ...current, conflict: false };
|
|
182
|
+
}
|
|
183
|
+
if (!force && (current.entry.content === null || versionOf(current.entry.content) !== version)) {
|
|
184
|
+
return { ok: false, conflict: true, problem: (0, i18n_1.t)({
|
|
185
|
+
en: `${current.path} has changed in the container since you opened it.`,
|
|
186
|
+
nl: `${current.path} is in de container veranderd sinds je het opende.`,
|
|
187
|
+
de: `${current.path} hat sich im Container geändert, seit Sie es geöffnet haben.`,
|
|
188
|
+
fr: `${current.path} a changé dans le conteneur depuis que vous l’avez ouvert.`,
|
|
189
|
+
es: `${current.path} ha cambiado en el contenedor desde que lo abriste.`,
|
|
190
|
+
}) };
|
|
191
|
+
}
|
|
192
|
+
const content = Buffer.from(text, 'utf8');
|
|
193
|
+
const pack = tar.pack();
|
|
194
|
+
pack.entry({ name: path.posix.basename(current.path), size: content.length, mode: current.entry.mode, uid: current.entry.uid, gid: current.entry.gid, mtime: new Date() }, content);
|
|
195
|
+
pack.finalize();
|
|
196
|
+
// `copyUIDGID`: de eigenaar en groep uit het archief, en dat zijn die van het oude bestand.
|
|
197
|
+
await (0, docker_client_1.getConnection)()
|
|
198
|
+
.docker.getContainer(id)
|
|
199
|
+
.putArchive(pack, { path: path.posix.dirname(current.path), copyUIDGID: '1' });
|
|
200
|
+
return { ok: true, version: versionOf(content) };
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
return { ok: false, conflict: false, problem: (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=file-edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-edit.js","sourceRoot":"","sources":["../electron/file-edit.ts"],"names":[],"mappings":"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"}
|
package/dist-electron/ipc.js
CHANGED
|
@@ -65,8 +65,10 @@ const run_command_1 = require("./run-command");
|
|
|
65
65
|
const memory_limit_1 = require("./memory-limit");
|
|
66
66
|
const cpu_limit_1 = require("./cpu-limit");
|
|
67
67
|
const container_rename_1 = require("./container-rename");
|
|
68
|
+
const file_edit_1 = require("./file-edit");
|
|
68
69
|
const processes_1 = require("./processes");
|
|
69
70
|
const container_duplicate_1 = require("./container-duplicate");
|
|
71
|
+
const container_adjust_1 = require("./container-adjust");
|
|
70
72
|
const container_commit_1 = require("./container-commit");
|
|
71
73
|
const environment_1 = require("./environment");
|
|
72
74
|
const log_export_1 = require("./log-export");
|
|
@@ -79,6 +81,7 @@ const container_events_1 = require("./container-events");
|
|
|
79
81
|
const event_store_1 = require("./event-store");
|
|
80
82
|
const events_1 = require("./events");
|
|
81
83
|
const files_1 = require("./files");
|
|
84
|
+
const volume_file_edit_1 = require("./volume-file-edit");
|
|
82
85
|
const volume_files_1 = require("./volume-files");
|
|
83
86
|
const self_update_1 = require("./self-update");
|
|
84
87
|
const settings_1 = require("./settings");
|
|
@@ -120,6 +123,14 @@ const restartPolicy = zod_1.z.object({
|
|
|
120
123
|
maximumRetryCount: zod_1.z.number().int().min(0).max(100),
|
|
121
124
|
});
|
|
122
125
|
const containerIds = zod_1.z.array(containerId).max(1000);
|
|
126
|
+
// Een variabele is NAAM=waarde; de naam begint niet met een cijfer en bevat geen =.
|
|
127
|
+
const adjustOptions = zod_1.z.object({
|
|
128
|
+
env: zod_1.z.array(zod_1.z.string().max(32_768).regex(/^[A-Za-z_][^=]*=/s)).max(1000),
|
|
129
|
+
ports: zod_1.z
|
|
130
|
+
.array(zod_1.z.object({ containerPort: zod_1.z.number().int().min(1).max(65535), protocol: zod_1.z.enum(['tcp', 'udp']), hostPort: zod_1.z.number().int().min(1).max(65535).nullable() }))
|
|
131
|
+
.max(100),
|
|
132
|
+
restart: zod_1.z.enum(['no', 'always', 'unless-stopped', 'on-failure']),
|
|
133
|
+
});
|
|
123
134
|
const duplicateOptions = zod_1.z.object({
|
|
124
135
|
name: zod_1.z.string().min(1).max(128),
|
|
125
136
|
ports: zod_1.z
|
|
@@ -133,6 +144,11 @@ const memoryBytes = zod_1.z.number().int().positive().max(1024 ** 4);
|
|
|
133
144
|
const cpuCount = zod_1.z.number().positive().max(1024);
|
|
134
145
|
const streamId = zod_1.z.string().min(1).max(64);
|
|
135
146
|
const logTail = zod_1.z.number().int().min(0).max(10_000);
|
|
147
|
+
// Een tijdvak in seconden sinds 1970; `until` voor `since` weigert Docker zelf ook, maar dan onduidelijk.
|
|
148
|
+
const logRange = zod_1.z
|
|
149
|
+
.object({ since: zod_1.z.number().int().min(0), until: zod_1.z.number().int().min(0).nullable() })
|
|
150
|
+
.refine((range) => range.until === null || range.until >= range.since)
|
|
151
|
+
.nullable();
|
|
136
152
|
// Een referentie mag een registryhost, een pad, een tag en een digest bevatten; ruimer dan
|
|
137
153
|
// dit wordt het niet, en alles wat er niet in past wijst de daemon toch af.
|
|
138
154
|
const imageReference = zod_1.z.string().min(1).max(256).regex(/^[\w./:@-]+$/);
|
|
@@ -165,6 +181,17 @@ const wslDistro = zod_1.z.string().min(1).max(64).regex(/^[\w.-]+$/);
|
|
|
165
181
|
// Volumenamen, netwerk-id's en contextnamen komen uit onze eigen lijst; dit is een grens,
|
|
166
182
|
// geen validatie van wat Docker toelaat.
|
|
167
183
|
const resourceName = zod_1.z.string().min(1).max(256);
|
|
184
|
+
/** Te bewerken tekst: iets ruimer dan het maximum van het lezen, want bewerken mag het bestand iets groter maken. */
|
|
185
|
+
const editText = zod_1.z.string().max(2 * 1024 * 1024);
|
|
186
|
+
/** De versie van een gelezen bestand (sha256), om bij opslaan tegen te controleren. */
|
|
187
|
+
const editVersion = zod_1.z.string().regex(/^[0-9a-f]{64}$/);
|
|
188
|
+
/** Laat kiezen welke bestanden erin gaan; leeg als er niets gekozen is. */
|
|
189
|
+
async function chooseFilesToUpload(sender) {
|
|
190
|
+
const owner = electron_1.BrowserWindow.fromWebContents(sender);
|
|
191
|
+
const options = { properties: ['openFile', 'multiSelections'] };
|
|
192
|
+
const choice = owner === null ? await electron_1.dialog.showOpenDialog(options) : await electron_1.dialog.showOpenDialog(owner, options);
|
|
193
|
+
return choice.canceled ? [] : choice.filePaths;
|
|
194
|
+
}
|
|
168
195
|
// Een extra naam in een netwerk. Docker laat hier hetzelfde toe als bij een containernaam.
|
|
169
196
|
const networkAlias = zod_1.z
|
|
170
197
|
.string()
|
|
@@ -663,13 +690,15 @@ function registerIpcHandlers() {
|
|
|
663
690
|
handle(channels_1.CHANNELS.containersRename, (_event, id, name) => (0, container_rename_1.renameContainer)(containerId.parse(id), resourceName.parse(name)));
|
|
664
691
|
handle(channels_1.CHANNELS.containersDuplicatePlan, (_event, id) => (0, container_duplicate_1.readDuplicatePlan)(containerId.parse(id)));
|
|
665
692
|
handle(channels_1.CHANNELS.containersDuplicate, (_event, id, options) => (0, container_duplicate_1.duplicateContainer)(containerId.parse(id), duplicateOptions.parse(options)));
|
|
693
|
+
handle(channels_1.CHANNELS.containersAdjustPlan, (_event, id) => (0, container_adjust_1.readAdjustPlan)(containerId.parse(id)));
|
|
694
|
+
handle(channels_1.CHANNELS.containersAdjust, (_event, id, options) => (0, container_adjust_1.adjustContainer)(containerId.parse(id), adjustOptions.parse(options)));
|
|
666
695
|
handle(channels_1.CHANNELS.containersProcesses, (_event, id) => (0, processes_1.readProcesses)(containerId.parse(id)));
|
|
667
696
|
handle(channels_1.CHANNELS.containersCommit, (_event, id, reference) => (0, container_commit_1.commitContainer)(containerId.parse(id), imageReference.parse(reference)));
|
|
668
697
|
handle(channels_1.CHANNELS.containersCpuLimit, (_event, id) => (0, cpu_limit_1.readCpuLimit)(containerId.parse(id)));
|
|
669
698
|
handle(channels_1.CHANNELS.containersEnvironment, (_event, id) => (0, environment_1.readEnvironment)(containerId.parse(id)));
|
|
670
699
|
handle(channels_1.CHANNELS.containersSetCpuLimit, (_event, id, cpus) => (0, cpu_limit_1.applyCpuLimit)(containerId.parse(id), cpuCount.parse(cpus)));
|
|
671
700
|
handle(channels_1.CHANNELS.containersSetMemoryLimit, (_event, id, bytes) => (0, memory_limit_1.applyMemoryLimit)(containerId.parse(id), memoryBytes.parse(bytes)));
|
|
672
|
-
handle(channels_1.CHANNELS.containersSaveLogs, (event, id, name) => (0, log_export_1.exportLogs)(containerId.parse(id), resourceName.parse(name), async (suggestedName) => {
|
|
701
|
+
handle(channels_1.CHANNELS.containersSaveLogs, (event, id, name, range) => (0, log_export_1.exportLogs)(containerId.parse(id), resourceName.parse(name), logRange.parse(range ?? null), async (suggestedName) => {
|
|
673
702
|
const owner = electron_1.BrowserWindow.fromWebContents(event.sender);
|
|
674
703
|
const options = { defaultPath: suggestedName, filters: [{ name: 'Log', extensions: ['log', 'txt'] }] };
|
|
675
704
|
const choice = owner === null ? await electron_1.dialog.showSaveDialog(options) : await electron_1.dialog.showSaveDialog(owner, options);
|
|
@@ -743,6 +772,14 @@ function registerIpcHandlers() {
|
|
|
743
772
|
handle(channels_1.CHANNELS.volumesPrune, (_event, all) => (0, volumes_1.pruneVolumes)(truthy.parse(all)));
|
|
744
773
|
handle(channels_1.CHANNELS.volumesBrowse, (_event, name, dir) => (0, volume_files_1.listVolumeDirectory)(resourceName.parse(name), containerPath.parse(dir)));
|
|
745
774
|
handle(channels_1.CHANNELS.volumesCloseBrowser, () => (0, volume_files_1.closeVolumeBrowser)());
|
|
775
|
+
handle(channels_1.CHANNELS.volumesReadText, (_event, name, file) => (0, volume_file_edit_1.readVolumeFile)(resourceName.parse(name), containerPath.parse(file)));
|
|
776
|
+
handle(channels_1.CHANNELS.volumesSaveText, (_event, name, file, text, version, force) => (0, volume_file_edit_1.saveVolumeFile)(resourceName.parse(name), containerPath.parse(file), editText.parse(text), editVersion.parse(version), truthy.parse(force)));
|
|
777
|
+
handle(channels_1.CHANNELS.volumesChooseAndUpload, async (event, name, dir) => {
|
|
778
|
+
const volume = resourceName.parse(name);
|
|
779
|
+
const target = containerPath.parse(dir);
|
|
780
|
+
const choice = await chooseFilesToUpload(event.sender);
|
|
781
|
+
return choice.length === 0 ? { ok: true, count: 0 } : (0, volume_file_edit_1.uploadToVolume)(volume, target, choice);
|
|
782
|
+
});
|
|
746
783
|
handle(channels_1.CHANNELS.volumesBackup, (event, name) => (0, volume_backup_1.backupVolume)(resourceName.parse(name), async (suggestedName) => {
|
|
747
784
|
const owner = electron_1.BrowserWindow.fromWebContents(event.sender);
|
|
748
785
|
const options = { defaultPath: suggestedName, filters: [{ name: (0, i18n_1.t)({ en: 'Backup', nl: 'Back-up', de: 'Sicherung', fr: 'Sauvegarde', es: 'Copia de seguridad' }), extensions: ['tar'] }] };
|
|
@@ -802,6 +839,7 @@ function registerIpcHandlers() {
|
|
|
802
839
|
handle(channels_1.CHANNELS.composeBuildable, (_event, name) => (0, service_build_1.listBuildable)(resourceName.parse(name)));
|
|
803
840
|
handle(channels_1.CHANNELS.composeRebuild, (_event, name, service) => (0, service_build_1.rebuildService)(resourceName.parse(name), resourceName.parse(service)));
|
|
804
841
|
handle(channels_1.CHANNELS.systemDiskUsage, () => (0, system_1.readDiskUsage)());
|
|
842
|
+
handle(channels_1.CHANNELS.systemSpaceUsage, () => (0, system_1.readSpaceUsage)());
|
|
805
843
|
handle(channels_1.CHANNELS.systemPrune, (_event, selection) => (0, system_1.pruneSystem)(pruneSelection.parse(selection)));
|
|
806
844
|
handle(channels_1.CHANNELS.navigationTakePending, () => (0, navigation_1.takePendingRoute)());
|
|
807
845
|
handle(channels_1.CHANNELS.assistantStatus, () => ({ configured: (0, assistant_key_1.hasApiKey)(), storageAvailable: (0, assistant_key_1.keyStoreAvailable)() }));
|
|
@@ -839,14 +877,11 @@ function registerIpcHandlers() {
|
|
|
839
877
|
return choice.canceled || choice.filePath === undefined ? null : choice.filePath;
|
|
840
878
|
}));
|
|
841
879
|
handle(channels_1.CHANNELS.filesUpload, (_event, id, dir, locals) => (0, files_1.uploadFiles)(containerId.parse(id), containerPath.parse(dir), localPaths.parse(locals)));
|
|
880
|
+
handle(channels_1.CHANNELS.filesReadText, (_event, id, file) => (0, file_edit_1.readEditableFile)(containerId.parse(id), containerPath.parse(file)));
|
|
881
|
+
handle(channels_1.CHANNELS.filesSaveText, (_event, id, file, text, version, force) => (0, file_edit_1.saveEditableFile)(containerId.parse(id), containerPath.parse(file), editText.parse(text), editVersion.parse(version), truthy.parse(force)));
|
|
842
882
|
handle(channels_1.CHANNELS.filesChooseAndUpload, async (event, id, dir) => {
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
const choice = owner === null ? await electron_1.dialog.showOpenDialog(options) : await electron_1.dialog.showOpenDialog(owner, options);
|
|
846
|
-
if (choice.canceled) {
|
|
847
|
-
return { ok: true, count: 0 };
|
|
848
|
-
}
|
|
849
|
-
return (0, files_1.uploadFiles)(containerId.parse(id), containerPath.parse(dir), choice.filePaths);
|
|
883
|
+
const choice = await chooseFilesToUpload(event.sender);
|
|
884
|
+
return choice.length === 0 ? { ok: true, count: 0 } : (0, files_1.uploadFiles)(containerId.parse(id), containerPath.parse(dir), choice);
|
|
850
885
|
});
|
|
851
886
|
handle(channels_1.CHANNELS.contextsList, () => (0, contexts_1.listContexts)(activeContext));
|
|
852
887
|
handle(channels_1.CHANNELS.contextsUse, (_event, name) => useContext(resourceName.parse(name)));
|
|
@@ -854,9 +889,11 @@ function registerIpcHandlers() {
|
|
|
854
889
|
handle(channels_1.CHANNELS.contextsRemove, (_event, name) => (0, contexts_1.removeContext)(resourceName.parse(name), activeContext));
|
|
855
890
|
handle(channels_1.CHANNELS.contextsTest, (_event, target) => testTarget(serverTestTarget.parse(target)));
|
|
856
891
|
handle(channels_1.CHANNELS.contextsTrustHostKey, (_event, name, shown) => hostKeys.trust(hostKeyName.parse(name), hostKeyFingerprint.parse(shown)));
|
|
857
|
-
handle(channels_1.CHANNELS.execOpen, (event, id, cols, rows) => {
|
|
892
|
+
handle(channels_1.CHANNELS.execOpen, (event, id, cols, rows, user) => {
|
|
858
893
|
const target = containerId.parse(id);
|
|
859
|
-
|
|
894
|
+
// Een gebruiker (fase 77), of `null` voor die van de image.
|
|
895
|
+
const as = zod_1.z.string().regex(exec_1.EXEC_USER).nullable().parse(user ?? null);
|
|
896
|
+
return openShell(event.sender.id, cols, rows, (size, onData, onEnd) => (0, exec_1.openExec)(target, size, onData, onEnd, undefined, as));
|
|
860
897
|
});
|
|
861
898
|
handle(channels_1.CHANNELS.execOpenHost, (event, cols, rows) => {
|
|
862
899
|
const transcript = new terminal_transcript_1.TerminalTranscript();
|
|
@@ -876,7 +913,7 @@ function registerIpcHandlers() {
|
|
|
876
913
|
handle(channels_1.CHANNELS.execClose, (event, id) => {
|
|
877
914
|
windows.get(event.sender.id)?.streams.close(streamId.parse(id));
|
|
878
915
|
});
|
|
879
|
-
handle(channels_1.CHANNELS.logsOpen, async (event, id, tail) => {
|
|
916
|
+
handle(channels_1.CHANNELS.logsOpen, async (event, id, tail, range) => {
|
|
880
917
|
const state = requireState(event.sender.id);
|
|
881
918
|
// Het id wordt uitgegeven vóór de stream bestaat, zodat een close() tijdens het openen
|
|
882
919
|
// niet in het luchtledige valt. Zie StreamRegistry.
|
|
@@ -884,7 +921,7 @@ function registerIpcHandlers() {
|
|
|
884
921
|
const channel = `${channels_1.CHANNELS.logsLines}:${reserved}`;
|
|
885
922
|
const stream = await (0, logs_1.openLogStream)(containerId.parse(id), logTail.parse(tail), (lines) => {
|
|
886
923
|
state.streams.send(channel, lines);
|
|
887
|
-
});
|
|
924
|
+
}, undefined, logRange.parse(range ?? null));
|
|
888
925
|
state.streams.attach(reserved, stream);
|
|
889
926
|
return reserved;
|
|
890
927
|
});
|