mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-11-03 14:58:18 +00:00
Share application adapter and diagnostic helpers
This commit is contained in:
1 parent
4027417bf5
commit
b9dcb0d4c7
26 files changed
+937
-305
No files matched your search
@@ -13,6 +13,7 @@ import { generateCredentialObject } from "@vrtmrz/livesync-commonlib/compat/repl
|
||||
import { compatGlobal } from "@vrtmrz/livesync-commonlib/compat/common/coreEnvFunctions";
|
||||
import { isUnauthorizedError } from "@vrtmrz/livesync-commonlib/compat/common/utils.doc";
|
||||
import { normaliseCouchDBConfiguration } from "@/common/couchdbConfiguration";
|
||||
import { isCouchDBVersionAtLeast, normaliseResponseHeaderKeys } from "@/modules/features/couchDBDiagnosticValues";
|
||||
|
||||
export const checkConfig = async (
|
||||
checkResultDiv: HTMLDivElement | undefined,
|
||||
@@ -89,19 +90,6 @@ export const checkConfig = async (
|
||||
addResult($msg("obsidianLiveSyncSettingTab.serverVersion", { info: serverBanner }));
|
||||
const versionMatch = serverBanner.match(/CouchDB(\/([0-9.]+))?/);
|
||||
const versionStr = versionMatch ? versionMatch[2] : "0.0.0";
|
||||
const versionParts = `${versionStr}.0.0.0`.split(".");
|
||||
// Compare version string with the target version.
|
||||
// version must be a string like "3.2.1" or "3.10.2", and must be two or three parts.
|
||||
function isGreaterThanOrEqual(version: string) {
|
||||
const targetParts = version.split(".");
|
||||
for (let i = 0; i < targetParts.length; i++) {
|
||||
// compare as number if possible (so 3.10 > 3.2, 3.10.1b > 3.10.1a)
|
||||
const result = versionParts[i].localeCompare(targetParts[i], undefined, { numeric: true });
|
||||
if (result > 0) return true;
|
||||
if (result < 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Admin check
|
||||
// for database creation and deletion
|
||||
if (!(editingSettings.couchDB_USER in responseConfig.admins)) {
|
||||
@@ -109,7 +97,7 @@ export const checkConfig = async (
|
||||
} else {
|
||||
addResult($msg("obsidianLiveSyncSettingTab.okAdminPrivileges"));
|
||||
}
|
||||
if (isGreaterThanOrEqual("3.2.0")) {
|
||||
if (isCouchDBVersionAtLeast(versionStr, "3.2.0")) {
|
||||
// HTTP user-authorization check
|
||||
if (responseConfig?.chttpd?.require_valid_user != "true") {
|
||||
isSuccessful = false;
|
||||
@@ -148,7 +136,7 @@ export const checkConfig = async (
|
||||
} else {
|
||||
addResult($msg("obsidianLiveSyncSettingTab.okWwwAuth"));
|
||||
}
|
||||
if (isGreaterThanOrEqual("3.2.0")) {
|
||||
if (isCouchDBVersionAtLeast(versionStr, "3.2.0")) {
|
||||
if (responseConfig?.chttpd?.enable_cors != "true") {
|
||||
isSuccessful = false;
|
||||
addResult($msg("obsidianLiveSyncSettingTab.errEnableCorsChttpd"));
|
||||
@@ -240,12 +228,7 @@ export const checkConfig = async (
|
||||
undefined,
|
||||
customHeaders
|
||||
);
|
||||
const responseHeaders = Object.fromEntries(
|
||||
Object.entries(rr.headers).map((e) => {
|
||||
e[0] = `${e[0]}`.toLowerCase();
|
||||
return e;
|
||||
})
|
||||
);
|
||||
const responseHeaders = normaliseResponseHeaderKeys(rr.headers);
|
||||
addResult($msg("obsidianLiveSyncSettingTab.msgOriginCheck", { org }));
|
||||
if (responseHeaders["access-control-allow-credentials"] != "true") {
|
||||
addResult($msg("obsidianLiveSyncSettingTab.errCorsNotAllowingCredentials"));
|
||||
|
||||
@@ -8,6 +8,7 @@ import { generateCredentialObject } from "@vrtmrz/livesync-commonlib/compat/repl
|
||||
import { compatGlobal } from "@vrtmrz/livesync-commonlib/compat/common/coreEnvFunctions";
|
||||
import { isUnauthorizedError } from "@vrtmrz/livesync-commonlib/compat/common/utils.doc";
|
||||
import { normaliseCouchDBConfiguration } from "@/common/couchdbConfiguration";
|
||||
import { isCouchDBVersionAtLeast, normaliseResponseHeaderKeys } from "@/modules/features/couchDBDiagnosticValues";
|
||||
|
||||
export type ResultMessage = { message: string; classes: string[] };
|
||||
export type ResultErrorMessage = { message: string; result: "error"; classes: string[] };
|
||||
@@ -26,24 +27,6 @@ export type ConfigCheckResult<T = unknown, U = unknown> =
|
||||
| ResultError<U>
|
||||
| ResultMessage
|
||||
| ResultErrorMessage;
|
||||
/**
|
||||
* Compares two version strings to determine if the baseVersion is greater than or equal to the version.
|
||||
* @param baseVersion a.b.c format
|
||||
* @param version a.b.c format
|
||||
* @returns true if baseVersion is greater than or equal to version, false otherwise
|
||||
*/
|
||||
function isGreaterThanOrEqual(baseVersion: string, version: string) {
|
||||
const versionParts = `${baseVersion}.0.0.0`.split(".");
|
||||
const targetParts = version.split(".");
|
||||
for (let i = 0; i < targetParts.length; i++) {
|
||||
// compare as number if possible (so 3.10 > 3.2, 3.10.1b > 3.10.1a)
|
||||
const result = versionParts[i].localeCompare(targetParts[i], undefined, { numeric: true });
|
||||
if (result > 0) return true;
|
||||
if (result < 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the remote CouchDB setting with the given key and value.
|
||||
* @param setting Connection settings
|
||||
@@ -153,7 +136,7 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) =>
|
||||
} else {
|
||||
addSuccess($msg("obsidianLiveSyncSettingTab.okAdminPrivileges"));
|
||||
}
|
||||
if (isGreaterThanOrEqual(versionStr, "3.2.0")) {
|
||||
if (isCouchDBVersionAtLeast(versionStr, "3.2.0")) {
|
||||
// HTTP user-authorization check
|
||||
if (responseConfig?.chttpd?.require_valid_user != "true") {
|
||||
addError(
|
||||
@@ -189,7 +172,7 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) =>
|
||||
} else {
|
||||
addSuccess($msg("obsidianLiveSyncSettingTab.okWwwAuth"));
|
||||
}
|
||||
if (isGreaterThanOrEqual(versionStr, "3.2.0")) {
|
||||
if (isCouchDBVersionAtLeast(versionStr, "3.2.0")) {
|
||||
if (responseConfig?.chttpd?.enable_cors != "true") {
|
||||
addError(
|
||||
$msg("obsidianLiveSyncSettingTab.errEnableCorsChttpd"),
|
||||
@@ -287,12 +270,7 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) =>
|
||||
undefined,
|
||||
customHeaders
|
||||
);
|
||||
const responseHeaders = Object.fromEntries(
|
||||
Object.entries(rr.headers).map((e) => {
|
||||
e[0] = `${e[0]}`.toLowerCase();
|
||||
return e;
|
||||
})
|
||||
);
|
||||
const responseHeaders = normaliseResponseHeaderKeys(rr.headers);
|
||||
addMessage($msg("obsidianLiveSyncSettingTab.msgOriginCheck", { org }));
|
||||
if (responseHeaders["access-control-allow-credentials"] != "true") {
|
||||
addErrorMessage($msg("obsidianLiveSyncSettingTab.errCorsNotAllowingCredentials"));
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
export function isCouchDBVersionAtLeast(baseVersion: string, targetVersion: string) {
|
||||
const versionParts = `${baseVersion}.0.0.0`.split(".");
|
||||
const targetParts = targetVersion.split(".");
|
||||
for (let i = 0; i < targetParts.length; i++) {
|
||||
const result = versionParts[i].localeCompare(targetParts[i], undefined, { numeric: true });
|
||||
if (result > 0) return true;
|
||||
if (result < 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function normaliseResponseHeaderKeys<T>(headers: Record<string, T>) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(headers).map((entry) => {
|
||||
entry[0] = `${entry[0]}`.toLowerCase();
|
||||
return entry;
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isCouchDBVersionAtLeast, normaliseResponseHeaderKeys } from "./couchDBDiagnosticValues";
|
||||
|
||||
describe("CouchDB diagnostic values", () => {
|
||||
describe("version comparison", () => {
|
||||
it.each([
|
||||
["3.10.2", "3.2.0", true],
|
||||
["3.2.0", "3.10.0", false],
|
||||
["3.2", "3.2.0", true],
|
||||
["3.10.1b", "3.10.1a", true],
|
||||
["3.10.1a", "3.10.1b", false],
|
||||
["3.x", "3.2", true],
|
||||
])("compares %s with %s", (baseVersion, targetVersion, expected) => {
|
||||
expect(isCouchDBVersionAtLeast(baseVersion, targetVersion)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("response header keys", () => {
|
||||
it("lower-cases keys while retaining last collision values and entry order", () => {
|
||||
const headers = { Server: "first", server: "last", Zed: "z", Alpha: "a" };
|
||||
|
||||
const normalised = normaliseResponseHeaderKeys(headers);
|
||||
|
||||
expect(normalised).toEqual({ server: "last", zed: "z", alpha: "a" });
|
||||
expect(Object.keys(normalised)).toEqual(["server", "zed", "alpha"]);
|
||||
expect(headers).toEqual({ Server: "first", server: "last", Zed: "z", Alpha: "a" });
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user