From 7298160c2a2606e23c363d63c99f89a0fd693e2c Mon Sep 17 00:00:00 2001
From: LiHaohua
Date: Tue, 21 Jul 2026 18:01:00 +0800
Subject: [PATCH] fix(site): drop email-match preflight; attribute ownership by
GitHub login
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The upload preview still blocked submissions whose deb Maintainer email was
not among the user's verified GitHub emails ("提交会被拒绝"), even though the
Worker and packages Actions moved to first-come-first-served ownership keyed on
the uploader's GitHub login.
- preview: replace the Maintainer-email match check with an uploader
attribution line; block only on danger verdict, not-logged-in, or version/
ownership conflicts.
- ownership/version preflight: derive the owner login from the index
Maintainer noreply address (best-effort; the server re-checks uploaded_by).
- my-packages: list packages owned by the logged-in login instead of by
matching Maintainer email.
- copy update in index.html to describe the first-come model.
Co-authored-by: Cursor
---
site/app.js | 34 ++++++++++++++++++----------------
site/index.html | 6 +++---
2 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/site/app.js b/site/app.js
index 10a6544..de82321 100644
--- a/site/app.js
+++ b/site/app.js
@@ -1,6 +1,6 @@
/* CardputerZero developer portal front-end. Same-origin API (see worker/). */
-import { parseDeb, compareDebVersions, extractEmail } from "/debparse.js";
+import { parseDeb, compareDebVersions, extractEmail, loginFromNoreply } from "/debparse.js";
// All decompression libraries are vendored at /vendor/ and served same-origin,
// so there is zero runtime dependency on a third-party CDN (availability,
@@ -198,26 +198,26 @@ async function renderPreview() {
$("p-noicon").classList.remove("hidden");
}
- // 邮箱归属预检
- const email = (parsed.email || "").toLowerCase();
- const mine = me && me.emails.includes(email);
- $("p-emailmatch").innerHTML = mine
- ? `Maintainer 邮箱与你的 GitHub 已验证邮箱匹配`
- : `Maintainer 邮箱 (${email || "缺失"}) 不在你的 GitHub 已验证邮箱里 — 提交会被拒绝${me && me.is_admin ? "(你是管理员,可豁免)" : ""}`;
+ // 上传者归属(包名先到先得,以 GitHub 账号为准,与 deb 里的 Maintainer 邮箱无关)
+ $("p-emailmatch").innerHTML = me
+ ? `将以 @${me.login} 的身份记录为上传者`
+ : `请先登录 GitHub 再提交`;
- // 版本 / 包名占用预检
+ // 版本 / 包名占用预检(所有权按上传者 GitHub 账号先到先得)
const idx = await loadIndex();
const entries = idx.get(c.Package) || [];
let verState = "", verOk = true;
if (!entries.length) {
- verState = `新包名,首次提交后归属于你`;
+ verState = `新包名,首次提交后归属于你${me ? `(@${me.login})` : ""}`;
} else {
- const owner = extractEmail(entries[0].Maintainer || "").toLowerCase();
- const owned = me && (me.emails.includes(owner) || me.is_admin);
+ // 前端只能读到线上索引里的 Maintainer,尽力从 noreply 地址反推 owner;
+ // 服务端会按记录的 uploaded_by 权威复核。
+ const ownerLogin = loginFromNoreply(entries[0].Maintainer || "");
+ const owned = me && (me.is_admin || (ownerLogin && ownerLogin === me.login.toLowerCase()));
const latest = entries.map((e) => e.Version).sort(compareDebVersions).pop();
- if (!owned) {
+ if (ownerLogin && !owned) {
verOk = false;
- verState = `包名已被他人占用(Maintainer: ${owner.slice(0, 2)}***),无法提交`;
+ verState = `包名已被 @${ownerLogin} 占用,只有其本人或管理员可以更新`;
} else if (compareDebVersions(c.Version, latest) <= 0) {
verOk = false;
verState = `版本 ${c.Version} 不高于线上已发布的 ${latest},请提升版本号`;
@@ -251,7 +251,7 @@ async function renderPreview() {
$("p-scripts-box").classList.add("hidden");
}
- const blocked = parsed.verdict === "danger" || (!mine && !(me && me.is_admin)) || !verOk;
+ const blocked = parsed.verdict === "danger" || !me || !verOk;
$("submit-btn").disabled = blocked;
$("submit-btn").textContent = blocked ? "存在阻断性问题,无法提交" : "提交到 AppStore";
$("preview-box").classList.remove("hidden");
@@ -292,8 +292,10 @@ async function renderMine() {
const mine = [];
for (const [name, entries] of idx) {
for (const e of entries) {
- const email = extractEmail(e.Maintainer || "").toLowerCase();
- if (me.emails.includes(email) || me.is_admin) mine.push({ name, ...e, email });
+ const ownerLogin = loginFromNoreply(e.Maintainer || "");
+ if (me.is_admin || (ownerLogin && ownerLogin === me.login.toLowerCase())) {
+ mine.push({ name, ...e, email: extractEmail(e.Maintainer || "").toLowerCase() });
+ }
}
}
if (!mine.length) {
diff --git a/site/index.html b/site/index.html
index 0668525..d31e8ee 100644
--- a/site/index.html
+++ b/site/index.html
@@ -96,8 +96,8 @@ CardputerZero 开发者中心
上传 / 管理 AppStore 软件包需要 GitHub 登录。
- 我们通过 GitHub 校验你的已验证邮箱:包的 Maintainer 邮箱必须是你本人,
- 同名包只有原作者(或管理员)可以更新和下架。
+ 包名先到先得:谁先上传某个包名,就归属于其 GitHub 账号,
+ 之后同名包只有原上传者(或管理员)可以更新和下架。
@@ -151,7 +151,7 @@ CardputerZero 开发者中心
| 包名 | 版本 | Maintainer | |
| 加载中… |
- 列表来自线上 APT 索引,只显示 Maintainer 邮箱属于你的包。可直接下载已发布的 .deb;下架会生成移除 PR。
+ 列表来自线上 APT 索引,只显示归属于你的包。可直接下载已发布的 .deb;下架会生成移除 PR。