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 name="viewport" content="width=device-width, initial-scale=1.0" />
<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">
</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." });
}
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) {
const status = result.conflict ? 403 : 400;
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,
repoUrl: null,
pluginName: row.label,
pluginVersion: null,
pluginVersion: row.last_used_version || null,
lastUsedVersion: row.last_used_version,
repo: null
};
}
@@ -134,7 +135,8 @@ export async function buildLicensePayload(row) {
repoFullName: info.fullName,
repoUrl: info.repoUrl,
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,
hostnames
};
@@ -152,25 +154,32 @@ export async function buildLicensePayload(row) {
repoFullName: row.repo_name,
repoUrl: repoEntry?.baseUrl ? `${repoEntry.baseUrl.replace(/\/$/, "")}/${row.repo_name}` : null,
pluginName: row.label,
pluginVersion: null,
pluginVersion: row.last_used_version || null,
lastUsedVersion: row.last_used_version,
repo: repoEntry,
hostnames
};
}
}
export async function touchLicenseHostname(license, hostname) {
export async function touchLicenseHostname(license, hostname, options = {}) {
const normalizedHost = normalizeHostname(hostname);
if (!normalizedHost) {
return { ok: false, error: "Ongeldige hostname." };
}
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) {
await db.query(
`UPDATE licenses SET primary_hostname = ?, primary_hostname_normalized = ?, last_version_check_at = NOW(), updated_at = NOW()
WHERE id = ?`,
[trimmed, normalizedHost, license.id]
);
updateFields.push("primary_hostname = ?", "primary_hostname_normalized = ?");
params.push(trimmed, normalizedHost);
} else if (license.primary_hostname_normalized !== normalizedHost) {
return {
ok: false,
@@ -178,9 +187,20 @@ export async function touchLicenseHostname(license, hostname) {
error: `Licentie hoort bij ${license.primary_hostname || "een andere site"}.`
};
} 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(
`INSERT INTO license_hostnames (license_id, hostname, normalized, first_seen_at, last_seen_at, hits)
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() {
await db.query(`
CREATE TABLE IF NOT EXISTS licenses (
@@ -33,11 +40,18 @@ async function createLicensesTable() {
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_version_check_at DATETIME NULL,
last_used_version VARCHAR(64) NULL,
primary_hostname VARCHAR(255) NULL,
primary_hostname_normalized VARCHAR(255) NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) 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() {

View File

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

View File

@@ -24,6 +24,7 @@ export default function LicenseManager() {
const [verifying, setVerifying] = useState(false);
const [verifyKey, setVerifyKey] = useState("");
const [verifyHostname, setVerifyHostname] = useState("");
const [verifyVersion, setVerifyVersion] = useState("");
const [newUserForm, setNewUserForm] = useState({
username: "",
name: "",
@@ -268,7 +269,8 @@ export default function LicenseManager() {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
key: verifyKey.trim(),
hostname: verifyHostname.trim()
hostname: verifyHostname.trim(),
currentVersion: verifyVersion.trim() || undefined
})
});
const data = await response.json().catch(() => ({}));
@@ -440,6 +442,14 @@ export default function LicenseManager() {
placeholder="voorbeeld.nl"
/>
</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}>
{verifying ? "Controleren…" : "Controleer licentie"}
</button>
@@ -447,11 +457,22 @@ export default function LicenseManager() {
{verifyStatus && verifyStatus.ok && verifyStatus.data?.license && (
<div className="state success inline">
<strong>Licentie geldig</strong>
<p>{verifyStatus.data.license.pluginName || "Plugin"}</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>
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>
</div>
)}