fix: preserve takeover and share token integrity
This commit is contained in:
@@ -38,8 +38,9 @@ def init_db():
|
|||||||
("authorizations", "takeover_enabled", "BOOLEAN DEFAULT 0"),
|
("authorizations", "takeover_enabled", "BOOLEAN DEFAULT 0"),
|
||||||
("authorizations", "takeover_mode", "VARCHAR DEFAULT 'immediate'"),
|
("authorizations", "takeover_mode", "VARCHAR DEFAULT 'immediate'"),
|
||||||
("authorizations", "takeover_delay_seconds", "INTEGER DEFAULT 30"),
|
("authorizations", "takeover_delay_seconds", "INTEGER DEFAULT 30"),
|
||||||
("avatars", "share_token", "VARCHAR DEFAULT ''"),
|
("avatars", "share_token", "VARCHAR DEFAULT NULL"),
|
||||||
)
|
)
|
||||||
|
_normalize_optional_unique_values()
|
||||||
|
|
||||||
|
|
||||||
def _try_add_columns(*cols):
|
def _try_add_columns(*cols):
|
||||||
@@ -51,3 +52,8 @@ def _try_add_columns(*cols):
|
|||||||
except Exception:
|
except Exception:
|
||||||
# 列已存在(或全新库由 create_all 建好)则忽略
|
# 列已存在(或全新库由 create_all 建好)则忽略
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_optional_unique_values():
|
||||||
|
with engine.begin() as conn:
|
||||||
|
conn.exec_driver_sql("UPDATE avatars SET share_token = NULL WHERE share_token = ''")
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Avatar(Base):
|
|||||||
photo_url = Column(String, default="")
|
photo_url = Column(String, default="")
|
||||||
emoji = Column(String, default="🤖")
|
emoji = Column(String, default="🤖")
|
||||||
status = Column(String, default="active") # active | inactive | training
|
status = Column(String, default="active") # active | inactive | training
|
||||||
share_token = Column(String, default="", unique=True, index=True) # 对外分享使用的不可猜测令牌
|
share_token = Column(String, nullable=True, default=None, unique=True, index=True) # 对外分享使用的不可猜测令牌
|
||||||
token_balance = Column(Integer, default=0)
|
token_balance = Column(Integer, default=0)
|
||||||
config = Column(JSON, default=dict)
|
config = Column(JSON, default=dict)
|
||||||
created_at = Column(DateTime, server_default=func.now())
|
created_at = Column(DateTime, server_default=func.now())
|
||||||
@@ -36,7 +36,7 @@ class Avatar(Base):
|
|||||||
"photoUrl": self.photo_url,
|
"photoUrl": self.photo_url,
|
||||||
"emoji": self.emoji,
|
"emoji": self.emoji,
|
||||||
"status": self.status,
|
"status": self.status,
|
||||||
"shareToken": self.share_token,
|
"shareToken": self.share_token or "",
|
||||||
"tokenBalance": self.token_balance,
|
"tokenBalance": self.token_balance,
|
||||||
"config": self.config or {},
|
"config": self.config or {},
|
||||||
"createdAt": _iso(self.created_at),
|
"createdAt": _iso(self.created_at),
|
||||||
|
|||||||
@@ -133,4 +133,3 @@ def delete_avatar(avatar_id: str, db: Session = Depends(get_db)):
|
|||||||
db.delete(a)
|
db.delete(a)
|
||||||
db.commit()
|
db.commit()
|
||||||
return ok({"success": True})
|
return ok({"success": True})
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,12 @@ class ChatOrchestrationTests(unittest.TestCase):
|
|||||||
self.assertNotIn("config", payload)
|
self.assertNotIn("config", payload)
|
||||||
self.assertNotIn("ownerId", payload)
|
self.assertNotIn("ownerId", payload)
|
||||||
|
|
||||||
|
def test_unshared_avatars_do_not_reuse_a_unique_share_token(self):
|
||||||
|
first = Avatar(name="first")
|
||||||
|
second = Avatar(name="second")
|
||||||
|
self.assertIsNone(first.share_token)
|
||||||
|
self.assertIsNone(second.share_token)
|
||||||
|
|
||||||
def test_standard_answer_can_be_emitted_as_sse_chunks(self):
|
def test_standard_answer_can_be_emitted_as_sse_chunks(self):
|
||||||
self.assertEqual(list(_iter_text_chunks("标准答案内容", size=2)), ["标准", "答案", "内容"])
|
self.assertEqual(list(_iter_text_chunks("标准答案内容", size=2)), ["标准", "答案", "内容"])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user