fix(game_base): 修复登录注册与 Odoo 18 鉴权对齐 + world.html 登录闸门

- game_api.py: request.session.authenticate 改为 Odoo 18 签名
  authenticate(db, {'type':'password','login':...,'password':...}),
  修复此前多传参数导致的 500 / Access Denied
- game_api.py: 注册成功后先 commit 再自动登录(避免新用户事务未提交导致 Access Denied)
- game_api.py: 登录 authenticate 包 try/except,错误密码返回干净报错而非 500
- world.html: 新增登录闸门——未登录跳转 login.html?next=world.html,
  已登录显示左上角昵称+退出;进入游戏即需登录(与 Odoo 打通)
This commit is contained in:
李鹏宇 2026-07-23 16:44:15 +08:00
parent c1af173f85
commit 63449893ca
2 changed files with 42 additions and 2 deletions

View File

@ -129,7 +129,11 @@ class GameApiController(http.Controller):
password = data.get('password') or ''
if not login or not password:
return _json({'ok': False, 'error': '账号和密码必填'})
uid = request.session.authenticate(db, login, password)
try:
auth_info = request.session.authenticate(db, {'type': 'password', 'login': login, 'password': password})
uid = auth_info['uid']
except Exception:
return _json({'ok': False, 'error': '账号或密码错误'})
if uid:
user = request.env['res.users'].sudo().browse(uid)
return _json({'ok': True, 'uid': uid, 'name': user.name, 'login': user.login})
@ -159,8 +163,10 @@ class GameApiController(http.Controller):
'password': password,
'groups_id': [(6, 0, [portal.id])],
})
request.env.cr.commit() # 让新用户立即对其他游标可见,便于随后自动登录
db = request.session.db or 'game'
uid = request.session.authenticate(db, login, password)
auth_info = request.session.authenticate(db, {'type': 'password', 'login': login, 'password': password})
uid = auth_info['uid']
if uid:
return _json({'ok': True, 'uid': uid, 'name': user.name, 'login': user.login})
return _json({'ok': True, 'uid': user.id, 'name': user.name, 'login': user.login})

View File

@ -347,9 +347,22 @@ body { background: #0a0e17; overflow: hidden; font-family: 'Microsoft YaHei', sa
transition:opacity .2s ease,transform .2s ease;}
#worldNav .wn-item:hover .wn-text{opacity:1;transform:translateY(-50%) translateX(0);}
/* ===== 登录闸门 ===== */
#authSplash{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;
background:linear-gradient(160deg,#080c1a,#0e1730 48%,#15213f);color:#9aa6c4;
font-family:"Noto Sans SC",system-ui,sans-serif;font-size:15px;letter-spacing:3px;}
#authBar{position:fixed;top:12px;left:18px;z-index:60;display:none;align-items:center;gap:10px;
padding:7px 14px;border-radius:999px;background:rgba(10,16,30,.72);backdrop-filter:blur(10px);
border:1px solid rgba(255,255,255,.14);font-family:"Noto Sans SC",system-ui,sans-serif;font-size:13px;color:#e9edf6;}
#authBar .ab-name{color:#c77dff;font-weight:500;}
#authBar .ab-logout{cursor:pointer;color:#9aa6c4;border:1px solid rgba(255,255,255,.18);background:transparent;border-radius:8px;padding:4px 10px;font-family:inherit;font-size:12px;transition:.2s;}
#authBar .ab-logout:hover{color:#fff;border-color:#8b5cf6;}
</style>
</head>
<body>
<div id="authSplash">登录校验中…</div>
<div id="authBar"><span class="ab-name"></span><button class="ab-logout" type="button">退出</button></div>
<!-- 加载界面 -->
<div id="loadingScreen">
@ -3107,6 +3120,27 @@ loadSavedWorld(); // 有存档则恢复玩家建造结果
init();
</script>
<script src="assets/game-api.js"></script>
<script>
// ===== 登录闸门:未登录跳登录页;已登录显示昵称+退出 =====
(async () => {
const splash = document.getElementById('authSplash');
const bar = document.getElementById('authBar');
try {
const me = await API.me();
if (!me || !me.uid) { location.replace('login.html?next=world.html'); return; }
bar.querySelector('.ab-name').textContent = me.name || me.login;
bar.style.display = 'flex';
bar.querySelector('.ab-logout').onclick = async () => {
try { await API.logout(); } catch (e) {}
location.replace('login.html');
};
} catch (e) {
location.replace('login.html?next=world.html'); return;
} finally {
if (splash) splash.remove();
}
})();
</script>
<script src="assets/world-app.js"></script>
</body>
</html>