Spaces:
Runtime error
Runtime error
Upload 2 files
Browse files- persistent_user_manager.py +112 -36
persistent_user_manager.py
CHANGED
|
@@ -56,12 +56,21 @@ class PersistentUserManager:
|
|
| 56 |
os.makedirs(self.session_data_dir, exist_ok=True)
|
| 57 |
logger.warning(f"フォールバック: ローカルディレクトリを使用 {self.user_data_dir}")
|
| 58 |
|
| 59 |
-
def _ensure_cookie_manager(self):
|
| 60 |
-
"""Cookie
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
return
|
| 63 |
|
| 64 |
try:
|
|
|
|
|
|
|
| 65 |
# セキュアなパスワードを生成(環境変数から取得、なければ生成)
|
| 66 |
cookie_password = os.getenv("MARI_COOKIE_PASSWORD", "mari_chat_secure_key_2024")
|
| 67 |
|
|
@@ -76,63 +85,86 @@ class PersistentUserManager:
|
|
| 76 |
|
| 77 |
self.cookies = cookies
|
| 78 |
self._cookie_initialized = True
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
|
| 81 |
except Exception as e:
|
| 82 |
logger.error(f"Cookie管理初期化エラー: {e}")
|
| 83 |
# フォールバック: セッション状態のみ使用
|
| 84 |
self.cookies = None
|
| 85 |
self._cookie_initialized = True
|
|
|
|
| 86 |
|
| 87 |
-
def get_or_create_user_id(self) -> str:
|
| 88 |
"""
|
| 89 |
ユーザーIDを取得または新規作成(Cookie連携・重複防止)
|
| 90 |
|
|
|
|
|
|
|
|
|
|
| 91 |
Returns:
|
| 92 |
ユーザーID
|
| 93 |
"""
|
| 94 |
try:
|
| 95 |
-
# 最優先: 既にStreamlitセッション状態にuser_id
|
| 96 |
-
if 'user_id' in st.session_state:
|
| 97 |
existing_id = st.session_state.user_id
|
| 98 |
if existing_id and self._is_valid_uuid(existing_id):
|
| 99 |
logger.debug(f"Streamlitセッション状態からユーザーID使用: {existing_id[:8]}...")
|
| 100 |
return existing_id
|
| 101 |
|
| 102 |
-
# 重複チェック防止:
|
| 103 |
-
if hasattr(st.session_state, 'persistent_user_id_checked'):
|
| 104 |
existing_id = st.session_state.get('persistent_user_id')
|
| 105 |
if existing_id and self._is_valid_uuid(existing_id):
|
| 106 |
logger.debug(f"既にチェック済みのユーザーID使用: {existing_id[:8]}...")
|
| 107 |
return existing_id
|
| 108 |
|
| 109 |
-
#
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
self.
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
st.session_state.persistent_user_id_checked = True
|
| 117 |
-
logger.info(f"
|
| 118 |
return user_id
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
|
|
|
|
|
|
| 126 |
st.session_state.persistent_user_id_checked = True
|
| 127 |
-
logger.info(f"
|
| 128 |
return user_id
|
| 129 |
|
| 130 |
-
# 3. 新規ユーザーIDを作成
|
| 131 |
-
user_id = self._create_new_user()
|
| 132 |
-
st.session_state.persistent_user_id_checked = True
|
| 133 |
-
logger.info(f"新規ユーザーID作成: {user_id[:8]}...")
|
| 134 |
-
return user_id
|
| 135 |
-
|
| 136 |
except Exception as e:
|
| 137 |
logger.error(f"ユーザーID取得エラー: {e}")
|
| 138 |
# フォールバック: 一時的なIDを生成
|
|
@@ -144,16 +176,19 @@ class PersistentUserManager:
|
|
| 144 |
def _get_user_id_from_cookie(self) -> Optional[str]:
|
| 145 |
"""CookieからユーザーIDを取得"""
|
| 146 |
try:
|
| 147 |
-
# Cookie
|
| 148 |
self._ensure_cookie_manager()
|
| 149 |
|
| 150 |
if self.cookies is None:
|
|
|
|
| 151 |
return None
|
| 152 |
|
| 153 |
user_id = self.cookies.get(self.cookie_name)
|
| 154 |
if user_id and self._is_valid_uuid(user_id):
|
|
|
|
| 155 |
return user_id
|
| 156 |
|
|
|
|
| 157 |
return None
|
| 158 |
|
| 159 |
except Exception as e:
|
|
@@ -163,10 +198,13 @@ class PersistentUserManager:
|
|
| 163 |
def _set_user_id_cookie(self, user_id: str):
|
| 164 |
"""ユーザーIDをCookieに設定"""
|
| 165 |
try:
|
| 166 |
-
# Cookie
|
| 167 |
-
self.
|
|
|
|
|
|
|
| 168 |
|
| 169 |
if self.cookies is None:
|
|
|
|
| 170 |
return
|
| 171 |
|
| 172 |
# Cookieの有効期限を設定
|
|
@@ -375,8 +413,8 @@ class PersistentUserManager:
|
|
| 375 |
|
| 376 |
# Cookieも削除
|
| 377 |
try:
|
| 378 |
-
# Cookie
|
| 379 |
-
self._ensure_cookie_manager()
|
| 380 |
|
| 381 |
if self.cookies:
|
| 382 |
if self.cookie_name in self.cookies:
|
|
@@ -388,6 +426,8 @@ class PersistentUserManager:
|
|
| 388 |
# セッション状態からも削除
|
| 389 |
if 'persistent_user_id' in st.session_state:
|
| 390 |
del st.session_state.persistent_user_id
|
|
|
|
|
|
|
| 391 |
|
| 392 |
return True
|
| 393 |
|
|
@@ -395,6 +435,42 @@ class PersistentUserManager:
|
|
| 395 |
logger.error(f"ユーザーデータ削除エラー: {e}")
|
| 396 |
return False
|
| 397 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
def list_all_users(self) -> List[Dict[str, Any]]:
|
| 399 |
"""
|
| 400 |
全ユーザーの一覧を取得(管理用)
|
|
|
|
| 56 |
os.makedirs(self.session_data_dir, exist_ok=True)
|
| 57 |
logger.warning(f"フォールバック: ローカルディレクトリを使用 {self.user_data_dir}")
|
| 58 |
|
| 59 |
+
def _ensure_cookie_manager(self, force_init: bool = False):
|
| 60 |
+
"""Cookie管理システムの初期化(初回またはフルリセット時のみ)"""
|
| 61 |
+
# 既に初期化済みで、強制初期化でない場合はスキップ
|
| 62 |
+
if self._cookie_initialized and not force_init:
|
| 63 |
+
return
|
| 64 |
+
|
| 65 |
+
# アプリ全体でのCookie初期化状態をチェック(グローバルフラグ)
|
| 66 |
+
if not force_init and st.session_state.get('cookie_manager_initialized', False):
|
| 67 |
+
logger.debug("Cookie管理システム既に初期化済み - スキップ")
|
| 68 |
+
self._cookie_initialized = True
|
| 69 |
return
|
| 70 |
|
| 71 |
try:
|
| 72 |
+
logger.info("Cookie管理システム初期化開始...")
|
| 73 |
+
|
| 74 |
# セキュアなパスワードを生成(環境変数から取得、なければ生成)
|
| 75 |
cookie_password = os.getenv("MARI_COOKIE_PASSWORD", "mari_chat_secure_key_2024")
|
| 76 |
|
|
|
|
| 85 |
|
| 86 |
self.cookies = cookies
|
| 87 |
self._cookie_initialized = True
|
| 88 |
+
|
| 89 |
+
# グローバルフラグを設定(アプリ全体で一度だけ初期化)
|
| 90 |
+
st.session_state.cookie_manager_initialized = True
|
| 91 |
+
|
| 92 |
+
logger.info("Cookie管理システム初期化完了")
|
| 93 |
|
| 94 |
except Exception as e:
|
| 95 |
logger.error(f"Cookie管理初期化エラー: {e}")
|
| 96 |
# フォールバック: セッション状態のみ使用
|
| 97 |
self.cookies = None
|
| 98 |
self._cookie_initialized = True
|
| 99 |
+
st.session_state.cookie_manager_initialized = True
|
| 100 |
|
| 101 |
+
def get_or_create_user_id(self, force_reset: bool = False) -> str:
|
| 102 |
"""
|
| 103 |
ユーザーIDを取得または新規作成(Cookie連携・重複防止)
|
| 104 |
|
| 105 |
+
Args:
|
| 106 |
+
force_reset: フルリセット時のみTrue
|
| 107 |
+
|
| 108 |
Returns:
|
| 109 |
ユーザーID
|
| 110 |
"""
|
| 111 |
try:
|
| 112 |
+
# 最優先: 既にStreamlitセッション状態にuser_idがある場合はそれを使用(フルリセット以外)
|
| 113 |
+
if not force_reset and 'user_id' in st.session_state:
|
| 114 |
existing_id = st.session_state.user_id
|
| 115 |
if existing_id and self._is_valid_uuid(existing_id):
|
| 116 |
logger.debug(f"Streamlitセッション状態からユーザーID使用: {existing_id[:8]}...")
|
| 117 |
return existing_id
|
| 118 |
|
| 119 |
+
# 重複チェック防止: 既にセッション状態にある場合はそれを使用(フルリセット以外)
|
| 120 |
+
if not force_reset and hasattr(st.session_state, 'persistent_user_id_checked'):
|
| 121 |
existing_id = st.session_state.get('persistent_user_id')
|
| 122 |
if existing_id and self._is_valid_uuid(existing_id):
|
| 123 |
logger.debug(f"既にチェック済みのユーザーID使用: {existing_id[:8]}...")
|
| 124 |
return existing_id
|
| 125 |
|
| 126 |
+
# Cookie初期化は初回またはフルリセット時のみ
|
| 127 |
+
if not self._cookie_initialized or force_reset:
|
| 128 |
+
# 1. CookieからユーザーIDを取得
|
| 129 |
+
user_id = self._get_user_id_from_cookie()
|
| 130 |
+
|
| 131 |
+
if user_id and self._is_valid_user_id(user_id):
|
| 132 |
+
# 有効なユーザーIDが存在
|
| 133 |
+
self._update_user_access_time(user_id)
|
| 134 |
+
st.session_state.persistent_user_id = user_id
|
| 135 |
+
st.session_state.persistent_user_id_checked = True
|
| 136 |
+
logger.info(f"CookieからユーザーID取得: {user_id[:8]}...")
|
| 137 |
+
return user_id
|
| 138 |
+
|
| 139 |
+
# 2. セッション状態から取得を試行(Cookieが無効な場合のみ)
|
| 140 |
+
if not force_reset:
|
| 141 |
+
user_id = st.session_state.get('persistent_user_id')
|
| 142 |
+
if user_id and self._is_valid_user_id(user_id):
|
| 143 |
+
# セッション状態にあるIDを使用してCookieを更新
|
| 144 |
+
self._set_user_id_cookie(user_id)
|
| 145 |
+
self._update_user_access_time(user_id)
|
| 146 |
+
st.session_state.persistent_user_id_checked = True
|
| 147 |
+
logger.info(f"セッション状態からユーザーID復元: {user_id[:8]}...")
|
| 148 |
+
return user_id
|
| 149 |
+
|
| 150 |
+
# 3. 新規ユーザーIDを作成
|
| 151 |
+
user_id = self._create_new_user()
|
| 152 |
st.session_state.persistent_user_id_checked = True
|
| 153 |
+
logger.info(f"新規ユーザーID作成: {user_id[:8]}...")
|
| 154 |
return user_id
|
| 155 |
+
else:
|
| 156 |
+
# Cookie初期化済みの場合は、セッション状態から取得
|
| 157 |
+
existing_id = st.session_state.get('persistent_user_id')
|
| 158 |
+
if existing_id and self._is_valid_uuid(existing_id):
|
| 159 |
+
logger.debug(f"Cookie初期化済み - セッション状態からユーザーID使用: {existing_id[:8]}...")
|
| 160 |
+
return existing_id
|
| 161 |
+
|
| 162 |
+
# フォールバック: 新規作成
|
| 163 |
+
user_id = self._create_new_user()
|
| 164 |
st.session_state.persistent_user_id_checked = True
|
| 165 |
+
logger.info(f"フォールバック新規ユーザーID作成: {user_id[:8]}...")
|
| 166 |
return user_id
|
| 167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
except Exception as e:
|
| 169 |
logger.error(f"ユーザーID取得エラー: {e}")
|
| 170 |
# フォールバック: 一時的なIDを生成
|
|
|
|
| 176 |
def _get_user_id_from_cookie(self) -> Optional[str]:
|
| 177 |
"""CookieからユーザーIDを取得"""
|
| 178 |
try:
|
| 179 |
+
# Cookie管理の初期化(初回のみ)
|
| 180 |
self._ensure_cookie_manager()
|
| 181 |
|
| 182 |
if self.cookies is None:
|
| 183 |
+
logger.debug("Cookie管理システム無効 - None返却")
|
| 184 |
return None
|
| 185 |
|
| 186 |
user_id = self.cookies.get(self.cookie_name)
|
| 187 |
if user_id and self._is_valid_uuid(user_id):
|
| 188 |
+
logger.debug(f"CookieからユーザーID取得: {user_id[:8]}...")
|
| 189 |
return user_id
|
| 190 |
|
| 191 |
+
logger.debug("Cookie内に有効なユーザーIDなし")
|
| 192 |
return None
|
| 193 |
|
| 194 |
except Exception as e:
|
|
|
|
| 198 |
def _set_user_id_cookie(self, user_id: str):
|
| 199 |
"""ユーザーIDをCookieに設定"""
|
| 200 |
try:
|
| 201 |
+
# Cookie管理システムが初期化されていない場合はスキップ
|
| 202 |
+
if not self._cookie_initialized:
|
| 203 |
+
logger.debug("Cookie管理システム未初期化 - Cookie設定スキップ")
|
| 204 |
+
return
|
| 205 |
|
| 206 |
if self.cookies is None:
|
| 207 |
+
logger.debug("Cookie管理システム無効 - Cookie設定スキップ")
|
| 208 |
return
|
| 209 |
|
| 210 |
# Cookieの有効期限を設定
|
|
|
|
| 413 |
|
| 414 |
# Cookieも削除
|
| 415 |
try:
|
| 416 |
+
# Cookie管理の強制初期化(フルリセット時)
|
| 417 |
+
self._ensure_cookie_manager(force_init=True)
|
| 418 |
|
| 419 |
if self.cookies:
|
| 420 |
if self.cookie_name in self.cookies:
|
|
|
|
| 426 |
# セッション状態からも削除
|
| 427 |
if 'persistent_user_id' in st.session_state:
|
| 428 |
del st.session_state.persistent_user_id
|
| 429 |
+
if 'persistent_user_id_checked' in st.session_state:
|
| 430 |
+
del st.session_state.persistent_user_id_checked
|
| 431 |
|
| 432 |
return True
|
| 433 |
|
|
|
|
| 435 |
logger.error(f"ユーザーデータ削除エラー: {e}")
|
| 436 |
return False
|
| 437 |
|
| 438 |
+
def full_reset_user_session(self) -> str:
|
| 439 |
+
"""
|
| 440 |
+
フルリセット(Cookie初期化を含む)
|
| 441 |
+
|
| 442 |
+
Returns:
|
| 443 |
+
新しいユーザーID
|
| 444 |
+
"""
|
| 445 |
+
try:
|
| 446 |
+
logger.info("フルリセット開始 - Cookie初期化を含む")
|
| 447 |
+
|
| 448 |
+
# セッション状態をクリア
|
| 449 |
+
if 'persistent_user_id' in st.session_state:
|
| 450 |
+
del st.session_state.persistent_user_id
|
| 451 |
+
if 'persistent_user_id_checked' in st.session_state:
|
| 452 |
+
del st.session_state.persistent_user_id_checked
|
| 453 |
+
if 'cookie_manager_initialized' in st.session_state:
|
| 454 |
+
del st.session_state.cookie_manager_initialized
|
| 455 |
+
|
| 456 |
+
# Cookie初期化フラグをリセット
|
| 457 |
+
self._cookie_initialized = False
|
| 458 |
+
self.cookies = None
|
| 459 |
+
|
| 460 |
+
# 新しいユーザーIDを作成(強制リセット)
|
| 461 |
+
new_user_id = self.get_or_create_user_id(force_reset=True)
|
| 462 |
+
|
| 463 |
+
logger.info(f"フルリセット完了: {new_user_id[:8]}...")
|
| 464 |
+
return new_user_id
|
| 465 |
+
|
| 466 |
+
except Exception as e:
|
| 467 |
+
logger.error(f"フルリセットエラー: {e}")
|
| 468 |
+
# フォールバック
|
| 469 |
+
import uuid
|
| 470 |
+
fallback_id = str(uuid.uuid4())
|
| 471 |
+
st.session_state.persistent_user_id = fallback_id
|
| 472 |
+
return fallback_id
|
| 473 |
+
|
| 474 |
def list_all_users(self) -> List[Dict[str, Any]]:
|
| 475 |
"""
|
| 476 |
全ユーザーの一覧を取得(管理用)
|