D109续③ · 登录改为代码仓库账号密码(告别长Token)
This commit is contained in:
parent
f5033df659
commit
ff38c723ca
@ -33,7 +33,7 @@ from engine import (
|
||||
|
||||
class Settings:
|
||||
APP_NAME = "语料采集系统 Corpus Agent"
|
||||
VERSION = "1.0.1"
|
||||
VERSION = "1.1.0"
|
||||
|
||||
# 存储路径
|
||||
DATA_DIR = Path(os.environ.get("CORPUS_DATA_DIR", "./data"))
|
||||
@ -85,6 +85,10 @@ class CorpusSave(BaseModel):
|
||||
class LoginRequest(BaseModel):
|
||||
gitea_token: str
|
||||
|
||||
class PasswordLoginRequest(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
|
||||
class ChatRequest(BaseModel):
|
||||
message: str
|
||||
persona: str = "zhuyuan" # zhuyuan | shuangyan
|
||||
@ -294,6 +298,50 @@ async def login(req: LoginRequest):
|
||||
}
|
||||
}
|
||||
|
||||
@app.post("/api/auth/login/password")
|
||||
async def login_with_password(req: PasswordLoginRequest):
|
||||
"""使用代码仓库账号密码登录(复用首页的 /api/verify 接口)"""
|
||||
import urllib.request
|
||||
|
||||
if not req.username.strip() or not req.password:
|
||||
raise HTTPException(400, "账号和密码不能为空")
|
||||
|
||||
try:
|
||||
# 调用本地验证接口(nginx: /api/verify → 127.0.0.1:3905/verify)
|
||||
verify_data = json.dumps({"user": req.username, "password": req.password}).encode()
|
||||
verify_req = urllib.request.Request(
|
||||
"http://127.0.0.1:3905/verify",
|
||||
data=verify_data,
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
with urllib.request.urlopen(verify_req, timeout=10) as resp:
|
||||
result = json.loads(resp.read().decode())
|
||||
|
||||
if not result.get("ok"):
|
||||
raise HTTPException(401, "账号或密码错误")
|
||||
|
||||
username = result.get("username", req.username)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"验证服务不可达: {str(e)}")
|
||||
|
||||
token = create_session(username)
|
||||
|
||||
# 统计现有语料
|
||||
corpus = load_corpus(username)
|
||||
|
||||
return {
|
||||
"ok": True,
|
||||
"token": token,
|
||||
"username": username,
|
||||
"stats": {
|
||||
"total_samples": len(corpus),
|
||||
"total_chars": sum(len(json.dumps(s, ensure_ascii=False)) for s in corpus),
|
||||
}
|
||||
}
|
||||
|
||||
@app.get("/api/auth/check")
|
||||
async def check_session(token: str = Query(...)):
|
||||
username = get_user_from_token(token)
|
||||
|
||||
@ -121,21 +121,24 @@
|
||||
<div class="header">
|
||||
<h1>🧠 语料采集系统 · Corpus Agent</h1>
|
||||
<p>自动采集 · 脱敏 · 格式化 · 对话式语料分析</p>
|
||||
<div class="version">v1.0.1 · 国作登字-2026-A-00037559</div>
|
||||
<div class="version">v1.1.0 · 国作登字-2026-A-00037559</div>
|
||||
</div>
|
||||
|
||||
<!-- Login -->
|
||||
<div class="card" id="login-section">
|
||||
<div class="login-box">
|
||||
<h2 style="margin-bottom:8px">登录</h2>
|
||||
<p style="color:#666; font-size:13px; margin-bottom:20px">
|
||||
使用 Gitea Access Token 登录
|
||||
<p style="color:#666; font-size:13px; margin-bottom:8px">
|
||||
使用代码仓库账号登录
|
||||
</p>
|
||||
<input type="password" id="token-input" placeholder="输入 Gitea Access Token">
|
||||
<input type="text" id="login-user" placeholder="Gitea 账号" style="width:260px" onkeydown="if(event.key==='Enter')login()">
|
||||
<br>
|
||||
<input type="password" id="login-pass" placeholder="密码" style="width:260px" onkeydown="if(event.key==='Enter')login()">
|
||||
<br>
|
||||
<button class="btn btn-primary" onclick="login()">登录</button>
|
||||
<div id="login-error" style="color:#ef4444;font-size:13px;margin-top:8px;display:none"></div>
|
||||
<p style="color:#999; font-size:12px; margin-top:12px">
|
||||
访问 <a href="https://guanghulab.com/user/settings/applications" target="_blank" style="color:#4a6cf7">Gitea → 设置 → 应用</a> 创建 Token
|
||||
与 <a href="https://guanghulab.com/" target="_blank" style="color:#4a6cf7">光湖联邦首页</a> 使用同一套账号
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -288,7 +291,7 @@
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="footer">
|
||||
语料采集系统 v1.0.1 · 铸渊 · ICE-GL-ZY001 · 国作登字-2026-A-00037559
|
||||
语料采集系统 v1.1.0 · 铸渊 · ICE-GL-ZY001 · 国作登字-2026-A-00037559
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -311,18 +314,22 @@ async function api(method, path, body) {
|
||||
|
||||
// ─── Login ─────────────────────────────────────────────────
|
||||
async function login() {
|
||||
const t = document.getElementById('token-input').value.trim();
|
||||
if (!t) return alert('请输入Token');
|
||||
const r = await fetch(`${API}/api/auth/login`, {
|
||||
const user = document.getElementById('login-user').value.trim();
|
||||
const pass = document.getElementById('login-pass').value;
|
||||
const errEl = document.getElementById('login-error');
|
||||
if (!user || !pass) { errEl.textContent = '请输入账号和密码'; errEl.style.display = 'block'; return; }
|
||||
errEl.style.display = 'none';
|
||||
const r = await fetch(`${API}/api/auth/login/password`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({gitea_token: t})
|
||||
body: JSON.stringify({username: user, password: pass})
|
||||
});
|
||||
const d = await r.json();
|
||||
if (!d.ok) return alert('登录失败: ' + JSON.stringify(d));
|
||||
if (!d.ok) { errEl.textContent = d.detail || '登录失败'; errEl.style.display = 'block'; return; }
|
||||
token = d.token;
|
||||
username = d.username;
|
||||
localStorage.setItem('corpus_token', token);
|
||||
document.getElementById('login-pass').value = '';
|
||||
document.getElementById('login-section').classList.add('hidden');
|
||||
document.getElementById('main-section').classList.remove('hidden');
|
||||
document.getElementById('display-name').textContent = username;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user