Refactor code structure for improved readability and maintainability

This commit is contained in:
2026-02-01 03:46:29 +00:00
parent 2473f3f708
commit 4292c62ad1
8 changed files with 150 additions and 87 deletions

68
dist/assets/index-B996h0A2.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/index.html vendored
View File

@@ -5,7 +5,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Siti Plugin Repo</title> <title>Siti Plugin Repo</title>
<script type="module" crossorigin src="/assets/index-garE9QaM.js"></script> <script type="module" crossorigin src="/assets/index-B996h0A2.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CFgb3VsA.css"> <link rel="stylesheet" crossorigin href="/assets/index-CFgb3VsA.css">
</head> </head>

View File

@@ -383,7 +383,11 @@ app.post("/api/licenses/verify", async (req, res) => {
return res.status(404).json({ valid: false, error: "Licentie niet gevonden." }); return res.status(404).json({ valid: false, error: "Licentie niet gevonden." });
} }
const result = await touchLicenseHostname(license, hostname); const rawVersion = req.body?.currentVersion ?? req.body?.pluginVersion ?? null;
const pluginVersion =
rawVersion && String(rawVersion).trim().length > 0 ? String(rawVersion).trim().slice(0, 64) : null;
const result = await touchLicenseHostname(license, hostname, { pluginVersion });
if (!result.ok) { if (!result.ok) {
const status = result.conflict ? 403 : 400; const status = result.conflict ? 403 : 400;
return res.status(status).json({ valid: false, error: result.error, boundHostname: license.primary_hostname }); return res.status(status).json({ valid: false, error: result.error, boundHostname: license.primary_hostname });

View File

@@ -113,7 +113,8 @@ export async function buildLicensePayload(row) {
repoFullName: row.repo_name, repoFullName: row.repo_name,
repoUrl: null, repoUrl: null,
pluginName: row.label, pluginName: row.label,
pluginVersion: null, pluginVersion: row.last_used_version || null,
lastUsedVersion: row.last_used_version,
repo: null repo: null
}; };
} }
@@ -134,7 +135,8 @@ export async function buildLicensePayload(row) {
repoFullName: info.fullName, repoFullName: info.fullName,
repoUrl: info.repoUrl, repoUrl: info.repoUrl,
pluginName: manifest?.plugin_name || info.name || row.label, pluginName: manifest?.plugin_name || info.name || row.label,
pluginVersion: manifest?.version || null, pluginVersion: manifest?.version || row.last_used_version || null,
lastUsedVersion: row.last_used_version,
repo: repoEntry, repo: repoEntry,
hostnames hostnames
}; };
@@ -152,25 +154,32 @@ export async function buildLicensePayload(row) {
repoFullName: row.repo_name, repoFullName: row.repo_name,
repoUrl: repoEntry?.baseUrl ? `${repoEntry.baseUrl.replace(/\/$/, "")}/${row.repo_name}` : null, repoUrl: repoEntry?.baseUrl ? `${repoEntry.baseUrl.replace(/\/$/, "")}/${row.repo_name}` : null,
pluginName: row.label, pluginName: row.label,
pluginVersion: null, pluginVersion: row.last_used_version || null,
lastUsedVersion: row.last_used_version,
repo: repoEntry, repo: repoEntry,
hostnames hostnames
}; };
} }
} }
export async function touchLicenseHostname(license, hostname) { export async function touchLicenseHostname(license, hostname, options = {}) {
const normalizedHost = normalizeHostname(hostname); const normalizedHost = normalizeHostname(hostname);
if (!normalizedHost) { if (!normalizedHost) {
return { ok: false, error: "Ongeldige hostname." }; return { ok: false, error: "Ongeldige hostname." };
} }
const trimmed = hostname.trim(); const trimmed = hostname.trim();
const rawVersion =
typeof options?.pluginVersion === "string" && options.pluginVersion.trim().length > 0
? options.pluginVersion.trim()
: null;
const pluginVersion = rawVersion ? rawVersion.slice(0, 64) : null;
const updateFields = [];
const params = [];
if (!license.primary_hostname_normalized) { if (!license.primary_hostname_normalized) {
await db.query( updateFields.push("primary_hostname = ?", "primary_hostname_normalized = ?");
`UPDATE licenses SET primary_hostname = ?, primary_hostname_normalized = ?, last_version_check_at = NOW(), updated_at = NOW() params.push(trimmed, normalizedHost);
WHERE id = ?`,
[trimmed, normalizedHost, license.id]
);
} else if (license.primary_hostname_normalized !== normalizedHost) { } else if (license.primary_hostname_normalized !== normalizedHost) {
return { return {
ok: false, ok: false,
@@ -178,9 +187,20 @@ export async function touchLicenseHostname(license, hostname) {
error: `Licentie hoort bij ${license.primary_hostname || "een andere site"}.` error: `Licentie hoort bij ${license.primary_hostname || "een andere site"}.`
}; };
} else { } else {
await db.query(`UPDATE licenses SET last_version_check_at = NOW(), updated_at = NOW() WHERE id = ?`, [license.id]); // No hostname change, but still keep the hostname casing in sync.
updateFields.push("primary_hostname = ?");
params.push(trimmed);
} }
updateFields.push("last_version_check_at = NOW()", "updated_at = NOW()");
if (pluginVersion) {
updateFields.push("last_used_version = ?");
params.push(pluginVersion);
}
await db.query(`UPDATE licenses SET ${updateFields.join(", ")} WHERE id = ?`, [...params, license.id]);
await db.query( await db.query(
`INSERT INTO license_hostnames (license_id, hostname, normalized, first_seen_at, last_seen_at, hits) `INSERT INTO license_hostnames (license_id, hostname, normalized, first_seen_at, last_seen_at, hits)
VALUES (?, ?, ?, NOW(), NOW(), 1) VALUES (?, ?, ?, NOW(), NOW(), 1)

View File

@@ -19,6 +19,13 @@ async function createUsersTable() {
} }
} }
async function ensureColumn(table, column, definition) {
const [columns] = await db.query(`SHOW COLUMNS FROM ${table} LIKE ?`, [column]);
if (columns.length === 0) {
await db.query(`ALTER TABLE ${table} ADD COLUMN ${definition}`);
}
}
async function createLicensesTable() { async function createLicensesTable() {
await db.query(` await db.query(`
CREATE TABLE IF NOT EXISTS licenses ( CREATE TABLE IF NOT EXISTS licenses (
@@ -33,11 +40,18 @@ async function createLicensesTable() {
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_version_check_at DATETIME NULL, last_version_check_at DATETIME NULL,
last_used_version VARCHAR(64) NULL,
primary_hostname VARCHAR(255) NULL, primary_hostname VARCHAR(255) NULL,
primary_hostname_normalized VARCHAR(255) NULL, primary_hostname_normalized VARCHAR(255) NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
`); `);
await ensureColumn(
"licenses",
"last_used_version",
"last_used_version VARCHAR(64) NULL AFTER last_version_check_at"
);
} }
async function createLicenseHostnamesTable() { async function createLicenseHostnamesTable() {

View File

@@ -15,14 +15,18 @@ export default function LicenseCard({ license }) {
</div> </div>
<div className="detail-list license-detail-list"> <div className="detail-list license-detail-list">
<div>
<span>Versie</span>
<strong>{license.pluginVersion || "-"}</strong>
</div>
<div> <div>
<span>Hostname</span> <span>Hostname</span>
<strong>{primaryHostname}</strong> <strong>{primaryHostname}</strong>
</div> </div>
<div>
<span>Huidige versie</span>
<strong>{license.lastUsedVersion || "-"}</strong>
</div>
<div>
<span>Laatste release</span>
<strong>{license.pluginVersion || "-"}</strong>
</div>
<div> <div>
<span>Aangemaakt</span> <span>Aangemaakt</span>
<strong>{formatDate(license.createdAt)}</strong> <strong>{formatDate(license.createdAt)}</strong>

View File

@@ -24,6 +24,7 @@ export default function LicenseManager() {
const [verifying, setVerifying] = useState(false); const [verifying, setVerifying] = useState(false);
const [verifyKey, setVerifyKey] = useState(""); const [verifyKey, setVerifyKey] = useState("");
const [verifyHostname, setVerifyHostname] = useState(""); const [verifyHostname, setVerifyHostname] = useState("");
const [verifyVersion, setVerifyVersion] = useState("");
const [newUserForm, setNewUserForm] = useState({ const [newUserForm, setNewUserForm] = useState({
username: "", username: "",
name: "", name: "",
@@ -268,7 +269,8 @@ export default function LicenseManager() {
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ body: JSON.stringify({
key: verifyKey.trim(), key: verifyKey.trim(),
hostname: verifyHostname.trim() hostname: verifyHostname.trim(),
currentVersion: verifyVersion.trim() || undefined
}) })
}); });
const data = await response.json().catch(() => ({})); const data = await response.json().catch(() => ({}));
@@ -440,6 +442,14 @@ export default function LicenseManager() {
placeholder="voorbeeld.nl" placeholder="voorbeeld.nl"
/> />
</label> </label>
<label className="field">
<span>Deze site draait versie</span>
<input
value={verifyVersion}
onChange={(event) => setVerifyVersion(event.target.value)}
placeholder="bijv. 1.9.3"
/>
</label>
<button className="ghost" type="submit" disabled={verifying}> <button className="ghost" type="submit" disabled={verifying}>
{verifying ? "Controleren…" : "Controleer licentie"} {verifying ? "Controleren…" : "Controleer licentie"}
</button> </button>
@@ -447,11 +457,22 @@ export default function LicenseManager() {
{verifyStatus && verifyStatus.ok && verifyStatus.data?.license && ( {verifyStatus && verifyStatus.ok && verifyStatus.data?.license && (
<div className="state success inline"> <div className="state success inline">
<strong>Licentie geldig</strong> <strong>Licentie geldig</strong>
<p>{verifyStatus.data.license.pluginName || "Plugin"}</p>
<p> <p>
{verifyStatus.data.license.pluginName || "Plugin"} versie {verifyStatus.data.license.pluginVersion || "-"} Huidige versie:{" "}
<strong>
{verifyStatus.data.license.lastUsedVersion ||
verifyStatus.data.license.pluginVersion ||
"-"}
</strong>
</p> </p>
<p> <p>
Gekoppeld aan: <strong>{verifyStatus.data.license.primaryHostname || "Nog niet gekoppeld"}</strong> Laatste release:{" "}
<strong>{verifyStatus.data.license.pluginVersion || "-"}</strong>
</p>
<p>
Gekoppeld aan:{" "}
<strong>{verifyStatus.data.license.primaryHostname || "Nog niet gekoppeld"}</strong>
</p> </p>
</div> </div>
)} )}