mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-02-08 08:14:21 +01:00
🎨 Implement HTTPS network serving (#16912)
* Add use TLS for network serving configuration option * kernel: Implement TLS certificate generation * kernel: server: Use https for fixed port proxy when needed * Allow exporting the CA Certificate file * Implement import and export of CA Certs
This commit is contained in:
parent
e7621b7a5f
commit
43ea6757d5
11 changed files with 759 additions and 10 deletions
|
|
@ -64,6 +64,44 @@ export const about = {
|
|||
<div class="fn__space"></div>
|
||||
<input class="b3-switch fn__flex-center" id="networkServe" type="checkbox"${window.siyuan.config.system.networkServe ? " checked" : ""}>
|
||||
</label>
|
||||
<label class="b3-label fn__flex">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.networkServeTLS}
|
||||
<div class="b3-label__text">${window.siyuan.languages.networkServeTLSTip}</div>
|
||||
</div>
|
||||
<div class="fn__space"></div>
|
||||
<input class="b3-switch fn__flex-center" id="networkServeTLS" type="checkbox"${window.siyuan.config.system.networkServeTLS ? " checked" : ""}${!window.siyuan.config.system.networkServe ? " disabled" : ""}>
|
||||
</label>
|
||||
<div class="fn__flex b3-label config__item${window.siyuan.config.system.networkServeTLS ? "" : " fn__none"}" id="exportCACertSection">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.exportCACert}
|
||||
<div class="b3-label__text">${window.siyuan.languages.exportCACertTip}</div>
|
||||
</div>
|
||||
<div class="fn__space"></div>
|
||||
<button class="b3-button b3-button--outline fn__size200 fn__flex-center" id="exportCACert">
|
||||
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.export}
|
||||
</button>
|
||||
</div>
|
||||
<div class="fn__flex b3-label config__item${window.siyuan.config.system.networkServeTLS ? "" : " fn__none"}" id="exportCABundleSection">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.exportCABundle}
|
||||
<div class="b3-label__text">${window.siyuan.languages.exportCABundleTip}</div>
|
||||
</div>
|
||||
<div class="fn__space"></div>
|
||||
<button class="b3-button b3-button--outline fn__size200 fn__flex-center" id="exportCABundle">
|
||||
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.export}
|
||||
</button>
|
||||
</div>
|
||||
<div class="fn__flex b3-label config__item${window.siyuan.config.system.networkServeTLS ? "" : " fn__none"}" id="importCABundleSection">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.importCABundle}
|
||||
<div class="b3-label__text">${window.siyuan.languages.importCABundleTip}</div>
|
||||
</div>
|
||||
<div class="fn__space"></div>
|
||||
<button class="b3-button b3-button--outline fn__size200 fn__flex-center" id="importCABundle">
|
||||
<svg><use xlink:href="#iconDownload"></use></svg>${window.siyuan.languages.import}
|
||||
</button>
|
||||
</div>
|
||||
<div class="b3-label${(window.siyuan.config.readonly || (isBrowser() && !isInIOS() && !isInAndroid() && !isIPad() && !isInHarmony())) ? " fn__none" : ""}">
|
||||
<div class="fn__flex">
|
||||
<div class="fn__flex-1">
|
||||
|
|
@ -102,7 +140,7 @@ export const about = {
|
|||
<div class="b3-label__text">${window.siyuan.languages.about18}</div>
|
||||
</div>
|
||||
<div class="fn__space"></div>
|
||||
<button data-type="open" data-url="${window.siyuan.config.system.networkServe ? window.siyuan.config.serverAddrs[0] : "http://127.0.0.1:"+ location.port}" class="b3-button b3-button--outline fn__size200 fn__flex-center">
|
||||
<button data-type="open" data-url="${window.siyuan.config.system.networkServeTLS ? "https" : "http"}://${window.siyuan.config.system.networkServe ? window.siyuan.config.serverAddrs[0] : "127.0.0.1"}:${location.port}" class="b3-button b3-button--outline fn__size200 fn__flex-center">
|
||||
<svg><use xlink:href="#iconLink"></use></svg>${window.siyuan.languages.about4}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -379,7 +417,12 @@ ${checkUpdateHTML}
|
|||
});
|
||||
});
|
||||
const networkServeElement = about.element.querySelector("#networkServe") as HTMLInputElement;
|
||||
const networkServeTLSElement = about.element.querySelector("#networkServeTLS") as HTMLInputElement;
|
||||
networkServeElement.addEventListener("change", () => {
|
||||
networkServeTLSElement.disabled = !networkServeElement.checked;
|
||||
if (!networkServeElement.checked) {
|
||||
networkServeTLSElement.checked = false;
|
||||
}
|
||||
fetchPost("/api/system/setNetworkServe", {networkServe: networkServeElement.checked}, () => {
|
||||
exportLayout({
|
||||
errorExit: true,
|
||||
|
|
@ -387,6 +430,60 @@ ${checkUpdateHTML}
|
|||
});
|
||||
});
|
||||
});
|
||||
networkServeTLSElement.addEventListener("change", () => {
|
||||
const exportCACertSection = about.element.querySelector("#exportCACertSection");
|
||||
const exportCABundleSection = about.element.querySelector("#exportCABundleSection");
|
||||
const importCABundleSection = about.element.querySelector("#importCABundleSection");
|
||||
if (exportCACertSection && exportCABundleSection && importCABundleSection) {
|
||||
if (networkServeTLSElement.checked) {
|
||||
exportCACertSection.classList.remove("fn__none");
|
||||
exportCABundleSection.classList.remove("fn__none");
|
||||
importCABundleSection.classList.remove("fn__none");
|
||||
} else {
|
||||
exportCACertSection.classList.add("fn__none");
|
||||
exportCABundleSection.classList.add("fn__none");
|
||||
importCABundleSection.classList.add("fn__none");
|
||||
}
|
||||
}
|
||||
fetchPost("/api/system/setNetworkServeTLS", {networkServeTLS: networkServeTLSElement.checked}, () => {
|
||||
exportLayout({
|
||||
errorExit: true,
|
||||
cb: exitSiYuan
|
||||
});
|
||||
});
|
||||
});
|
||||
about.element.querySelector("#exportCACert")?.addEventListener("click", () => {
|
||||
fetchPost("/api/system/exportTLSCACert", {}, (response) => {
|
||||
openByMobile(response.data.path);
|
||||
});
|
||||
});
|
||||
about.element.querySelector("#exportCABundle")?.addEventListener("click", () => {
|
||||
fetchPost("/api/system/exportTLSCABundle", {}, (response) => {
|
||||
openByMobile(response.data.path);
|
||||
});
|
||||
});
|
||||
about.element.querySelector("#importCABundle")?.addEventListener("click", () => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = ".zip";
|
||||
input.onchange = () => {
|
||||
if (input.files && input.files[0]) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", input.files[0]);
|
||||
fetch("/api/system/importTLSCABundle", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
}).then(res => res.json()).then((response) => {
|
||||
if (response.code === 0) {
|
||||
showMessage(window.siyuan.languages.importCABundleSuccess);
|
||||
} else {
|
||||
showMessage(response.msg, 6000, "error");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
});
|
||||
const lockScreenModeElement = about.element.querySelector("#lockScreenMode") as HTMLInputElement;
|
||||
lockScreenModeElement.addEventListener("change", () => {
|
||||
fetchPost("/api/system/setFollowSystemLockScreen", {lockScreenMode: lockScreenModeElement.checked ? 1 : 0}, () => {
|
||||
|
|
|
|||
|
|
@ -24,10 +24,42 @@ export const initAbout = () => {
|
|||
<div class="fn__space"></div>
|
||||
<input class="b3-switch fn__flex-center" id="networkServe" type="checkbox"${window.siyuan.config.system.networkServe ? " checked" : ""}>
|
||||
</label>
|
||||
<label class="b3-label fn__flex${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.networkServeTLS}
|
||||
<div class="b3-label__text">${window.siyuan.languages.networkServeTLSTip}</div>
|
||||
</div>
|
||||
<div class="fn__space"></div>
|
||||
<input class="b3-switch fn__flex-center" id="networkServeTLS" type="checkbox"${window.siyuan.config.system.networkServeTLS ? " checked" : ""}${!window.siyuan.config.system.networkServe ? " disabled" : ""}>
|
||||
</label>
|
||||
<div class="b3-label${window.siyuan.config.system.networkServeTLS ? "" : " fn__none"}" id="exportCACertSection">
|
||||
${window.siyuan.languages.exportCACert}
|
||||
<div class="fn__hr"></div>
|
||||
<button class="b3-button b3-button--outline fn__block" id="exportCACert">
|
||||
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.export}
|
||||
</button>
|
||||
<div class="b3-label__text">${window.siyuan.languages.exportCACertTip}</div>
|
||||
</div>
|
||||
<div class="b3-label${window.siyuan.config.system.networkServeTLS ? "" : " fn__none"}" id="exportCABundleSection">
|
||||
${window.siyuan.languages.exportCABundle}
|
||||
<div class="fn__hr"></div>
|
||||
<button class="b3-button b3-button--outline fn__block" id="exportCABundle">
|
||||
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.export}
|
||||
</button>
|
||||
<div class="b3-label__text">${window.siyuan.languages.exportCABundleTip}</div>
|
||||
</div>
|
||||
<div class="b3-label${window.siyuan.config.system.networkServeTLS ? "" : " fn__none"}" id="importCABundleSection">
|
||||
${window.siyuan.languages.importCABundle}
|
||||
<div class="fn__hr"></div>
|
||||
<button class="b3-button b3-button--outline fn__block" id="importCABundle">
|
||||
<svg><use xlink:href="#iconDownload"></use></svg>${window.siyuan.languages.import}
|
||||
</button>
|
||||
<div class="b3-label__text">${window.siyuan.languages.importCABundleTip}</div>
|
||||
</div>
|
||||
<div class="b3-label">
|
||||
${window.siyuan.languages.about2}
|
||||
<div class="fn__hr"></div>
|
||||
<a target="_blank" href="${window.siyuan.config.system.networkServe ? window.siyuan.config.serverAddrs[0] : "http://127.0.0.1:" + location.port}" class="b3-button b3-button--outline fn__block">
|
||||
<a target="_blank" href="${window.siyuan.config.system.networkServeTLS ? "https" : "http"}://${window.siyuan.config.system.networkServe ? window.siyuan.config.serverAddrs[0] : "127.0.0.1"}:${location.port}" class="b3-button b3-button--outline fn__block">
|
||||
<svg><use xlink:href="#iconLink"></use></svg>${window.siyuan.languages.about4}
|
||||
</a>
|
||||
<div class="b3-label__text">${window.siyuan.languages.about3.replace("${port}", location.port)}</div>
|
||||
|
|
@ -451,11 +483,67 @@ export const initAbout = () => {
|
|||
});
|
||||
});
|
||||
const networkServeElement = modelMainElement.querySelector("#networkServe") as HTMLInputElement;
|
||||
const networkServeTLSElement = modelMainElement.querySelector("#networkServeTLS") as HTMLInputElement;
|
||||
networkServeElement.addEventListener("change", () => {
|
||||
networkServeTLSElement.disabled = !networkServeElement.checked;
|
||||
if (!networkServeElement.checked) {
|
||||
networkServeTLSElement.checked = false;
|
||||
}
|
||||
fetchPost("/api/system/setNetworkServe", {networkServe: networkServeElement.checked}, () => {
|
||||
exitSiYuan();
|
||||
});
|
||||
});
|
||||
networkServeTLSElement.addEventListener("change", () => {
|
||||
const exportCACertSection = modelMainElement.querySelector("#exportCACertSection");
|
||||
const exportCABundleSection = modelMainElement.querySelector("#exportCABundleSection");
|
||||
const importCABundleSection = modelMainElement.querySelector("#importCABundleSection");
|
||||
if (exportCACertSection && exportCABundleSection && importCABundleSection) {
|
||||
if (networkServeTLSElement.checked) {
|
||||
exportCACertSection.classList.remove("fn__none");
|
||||
exportCABundleSection.classList.remove("fn__none");
|
||||
importCABundleSection.classList.remove("fn__none");
|
||||
} else {
|
||||
exportCACertSection.classList.add("fn__none");
|
||||
exportCABundleSection.classList.add("fn__none");
|
||||
importCABundleSection.classList.add("fn__none");
|
||||
}
|
||||
}
|
||||
fetchPost("/api/system/setNetworkServeTLS", {networkServeTLS: networkServeTLSElement.checked}, () => {
|
||||
exitSiYuan();
|
||||
});
|
||||
});
|
||||
modelMainElement.querySelector("#exportCACert")?.addEventListener("click", () => {
|
||||
fetchPost("/api/system/exportTLSCACert", {}, (response) => {
|
||||
openByMobile(response.data.path);
|
||||
});
|
||||
});
|
||||
modelMainElement.querySelector("#exportCABundle")?.addEventListener("click", () => {
|
||||
fetchPost("/api/system/exportTLSCABundle", {}, (response) => {
|
||||
openByMobile(response.data.path);
|
||||
});
|
||||
});
|
||||
modelMainElement.querySelector("#importCABundle")?.addEventListener("click", () => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = ".zip";
|
||||
input.onchange = () => {
|
||||
if (input.files && input.files[0]) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", input.files[0]);
|
||||
fetch("/api/system/importTLSCABundle", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
}).then(res => res.json()).then((response) => {
|
||||
if (response.code === 0) {
|
||||
showMessage(window.siyuan.languages.importCABundleSuccess);
|
||||
} else {
|
||||
showMessage(response.msg, 6000, "error");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
});
|
||||
const tokenElement = modelMainElement.querySelector("#token") as HTMLInputElement;
|
||||
tokenElement.addEventListener("change", () => {
|
||||
fetchPost("/api/system/setAPIToken", {token: tokenElement.value}, () => {
|
||||
|
|
|
|||
4
app/src/types/config.d.ts
vendored
4
app/src/types/config.d.ts
vendored
|
|
@ -1623,6 +1623,10 @@ declare namespace Config {
|
|||
* Whether to enable network serve (whether to allow connections from other devices)
|
||||
*/
|
||||
networkServe: boolean;
|
||||
/**
|
||||
* Whether to enable HTTPS for network serve (TLS encryption)
|
||||
*/
|
||||
networkServeTLS: boolean;
|
||||
/**
|
||||
* The operating system name determined at compile time (obtained using the command `go tool
|
||||
* dist list`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue