Persist scrape database write permissions

This commit is contained in:
2026-08-05 23:24:49 +02:00
parent 67753fb025
commit 19c6ee90e1
4 changed files with 24 additions and 8 deletions
+3 -3
View File
@@ -77,7 +77,7 @@ window.fetch = (input, init = {}) => {
const headers = new Headers(init.headers || (typeof input !== "string" ? input.headers : undefined)); const headers = new Headers(init.headers || (typeof input !== "string" ? input.headers : undefined));
const selectedMode = localStorage.getItem("catalog-maker:database-mode") || "local"; const selectedMode = localStorage.getItem("catalog-maker:database-mode") || "local";
const permissions = readDatabasePermissions(selectedMode); const permissions = readDatabasePermissions(selectedMode);
const localWritesEnabled = selectedMode === "local" && [ const localWritesEnabled = ["local", "scrape"].includes(selectedMode) && [
permissions.allowInsertToggle, permissions.allowInsertToggle,
permissions.allowUpdateToggle, permissions.allowUpdateToggle,
permissions.allowDeleteToggle, permissions.allowDeleteToggle,
@@ -1181,7 +1181,7 @@ function syncLocalDbFields(mode) {
localDbFields.hidden = mode !== "local"; localDbFields.hidden = mode !== "local";
} }
function syncDatabasePermissions(mode) { function syncDatabasePermissions(mode) {
const isReadOnly = mode === "live" || mode === "scrape"; const isReadOnly = mode === "live";
for (const input of permissionInputs) { for (const input of permissionInputs) {
input.disabled = isReadOnly; input.disabled = isReadOnly;
if (isReadOnly) if (isReadOnly)
@@ -1205,7 +1205,7 @@ function refreshDatabaseStatusLabel() {
const mode = localStorage.getItem("catalog-maker:database-mode") || "local"; const mode = localStorage.getItem("catalog-maker:database-mode") || "local";
const transactionMode = localStorage.getItem("catalog-maker:transaction-mode") || "transaction"; const transactionMode = localStorage.getItem("catalog-maker:transaction-mode") || "transaction";
const permissions = readDatabasePermissions(mode); const permissions = readDatabasePermissions(mode);
const writesEnabled = mode === "local" && (permissions.allowInsertToggle || permissions.allowUpdateToggle || permissions.allowDeleteToggle); const writesEnabled = ["local", "scrape"].includes(mode) && (permissions.allowInsertToggle || permissions.allowUpdateToggle || permissions.allowDeleteToggle);
const dbLabel = mode === "live" ? "Live 9bplus DB" : mode === "scrape" ? "Local scrape DB" : "Local 9bplus DB"; const dbLabel = mode === "live" ? "Live 9bplus DB" : mode === "scrape" ? "Local scrape DB" : "Local 9bplus DB";
const configuredDriver = databaseStatus.dataset.driver; const configuredDriver = databaseStatus.dataset.driver;
const connectionError = (mode === "local" && configuredDriver !== "mariadb") const connectionError = (mode === "local" && configuredDriver !== "mariadb")
+3 -3
View File
@@ -78,7 +78,7 @@ window.fetch = (input, init = {}) => {
const headers = new Headers(init.headers || (typeof input !== "string" ? input.headers : undefined)); const headers = new Headers(init.headers || (typeof input !== "string" ? input.headers : undefined));
const selectedMode = localStorage.getItem("catalog-maker:database-mode") || "local"; const selectedMode = localStorage.getItem("catalog-maker:database-mode") || "local";
const permissions = readDatabasePermissions(selectedMode); const permissions = readDatabasePermissions(selectedMode);
const localWritesEnabled = selectedMode === "local" && [ const localWritesEnabled = ["local", "scrape"].includes(selectedMode) && [
permissions.allowInsertToggle, permissions.allowInsertToggle,
permissions.allowUpdateToggle, permissions.allowUpdateToggle,
permissions.allowDeleteToggle, permissions.allowDeleteToggle,
@@ -1270,7 +1270,7 @@ function syncLocalDbFields(mode) {
} }
function syncDatabasePermissions(mode) { function syncDatabasePermissions(mode) {
const isReadOnly = mode === "live" || mode === "scrape"; const isReadOnly = mode === "live";
for (const input of permissionInputs) { for (const input of permissionInputs) {
input.disabled = isReadOnly; input.disabled = isReadOnly;
if (isReadOnly) input.checked = false; if (isReadOnly) input.checked = false;
@@ -1294,7 +1294,7 @@ function refreshDatabaseStatusLabel() {
const mode = localStorage.getItem("catalog-maker:database-mode") || "local"; const mode = localStorage.getItem("catalog-maker:database-mode") || "local";
const transactionMode = localStorage.getItem("catalog-maker:transaction-mode") || "transaction"; const transactionMode = localStorage.getItem("catalog-maker:transaction-mode") || "transaction";
const permissions = readDatabasePermissions(mode); const permissions = readDatabasePermissions(mode);
const writesEnabled = mode === "local" && ( const writesEnabled = ["local", "scrape"].includes(mode) && (
permissions.allowInsertToggle || permissions.allowUpdateToggle || permissions.allowDeleteToggle permissions.allowInsertToggle || permissions.allowUpdateToggle || permissions.allowDeleteToggle
); );
const dbLabel = mode === "live" ? "Live 9bplus DB" : mode === "scrape" ? "Local scrape DB" : "Local 9bplus DB"; const dbLabel = mode === "live" ? "Live 9bplus DB" : mode === "scrape" ? "Local scrape DB" : "Local 9bplus DB";
+1 -1
View File
@@ -259,7 +259,7 @@
<input type="checkbox" id="allowDeleteToggle" /> <input type="checkbox" id="allowDeleteToggle" />
<span>Allow delete</span> <span>Allow delete</span>
</label> </label>
<p class="settings-note">Write permissions are saved only for Local 9bplus DB. Live and scrape DB stay read-only here.</p> <p class="settings-note">Write permissions are saved separately for Local 9bplus DB and Local scrape DB. Live DB stays read-only.</p>
</fieldset> </fieldset>
<fieldset class="settings-group"> <fieldset class="settings-group">
+17 -1
View File
@@ -17,7 +17,7 @@ test.describe("database connection", () => {
await expect(page.locator("#localDbTestResult")).toContainText("Connected:"); await expect(page.locator("#localDbTestResult")).toContainText("Connected:");
}); });
test("keeps the scrape database as a separate read-only mode", async ({ page }) => { test("keeps the scrape database as a separate local mode with its own permissions", async ({ page }) => {
await page.goto("/"); await page.goto("/");
await page.locator("#settingsButton").click(); await page.locator("#settingsButton").click();
@@ -25,6 +25,22 @@ test.describe("database connection", () => {
await expect(page.locator('input[name="databaseMode"][value="live"] + span')).toHaveText("Live 9bplus DB"); await expect(page.locator('input[name="databaseMode"][value="live"] + span')).toHaveText("Live 9bplus DB");
await page.locator('input[name="databaseMode"][value="scrape"]').check(); await page.locator('input[name="databaseMode"][value="scrape"]').check();
await expect(page.locator("#databaseModeNote")).toContainText("Local scrape DB selected"); await expect(page.locator("#databaseModeNote")).toContainText("Local scrape DB selected");
await expect(page.locator("#allowInsertToggle")).toBeEnabled();
await expect(page.locator("#allowUpdateToggle")).toBeEnabled();
await expect(page.locator("#allowDeleteToggle")).toBeEnabled();
await page.locator("#allowUpdateToggle").check();
await page.reload();
await page.locator("#settingsButton").click();
await page.locator('input[name="databaseMode"][value="scrape"]').check();
await expect(page.locator("#allowUpdateToggle")).toBeChecked();
await page.locator('input[name="databaseMode"][value="local"]').check();
await expect(page.locator("#allowInsertToggle")).not.toBeChecked();
await expect(page.locator("#allowUpdateToggle")).not.toBeChecked();
await expect(page.locator("#allowDeleteToggle")).not.toBeChecked();
await page.locator('input[name="databaseMode"][value="live"]').check();
await expect(page.locator("#allowInsertToggle")).toBeDisabled(); await expect(page.locator("#allowInsertToggle")).toBeDisabled();
await expect(page.locator("#allowUpdateToggle")).toBeDisabled(); await expect(page.locator("#allowUpdateToggle")).toBeDisabled();
await expect(page.locator("#allowDeleteToggle")).toBeDisabled(); await expect(page.locator("#allowDeleteToggle")).toBeDisabled();