Get current authentication status.
(self, session=None)
| 286 | return False |
| 287 | |
| 288 | def get_auth_status(self, session=None) -> dict: |
| 289 | """Get current authentication status.""" |
| 290 | configured = self.is_configured() |
| 291 | hw_fingerprint = self.get_hardware_fingerprint() |
| 292 | hw_match = True |
| 293 | |
| 294 | if configured: |
| 295 | try: |
| 296 | with self._get_auth_conn() as conn: |
| 297 | cursor = conn.cursor() |
| 298 | cursor.execute("SELECT hardware_fingerprint, username FROM auth LIMIT 1") |
| 299 | row = cursor.fetchone() |
| 300 | if row: |
| 301 | hw_match = secrets.compare_digest(row['hardware_fingerprint'], hw_fingerprint) |
| 302 | except Exception: |
| 303 | hw_match = False |
| 304 | |
| 305 | authenticated = False |
| 306 | if session and session.get('authenticated'): |
| 307 | authenticated = True |
| 308 | |
| 309 | remaining_codes = 0 |
| 310 | if configured: |
| 311 | try: |
| 312 | with self._get_auth_conn() as conn: |
| 313 | cursor = conn.cursor() |
| 314 | cursor.execute("SELECT COUNT(*) FROM recovery_codes WHERE used = 0") |
| 315 | remaining_codes = cursor.fetchone()[0] |
| 316 | except Exception: |
| 317 | pass |
| 318 | |
| 319 | # First login: auth configured and encrypted DB exists (needs decryption) |
| 320 | first_login = configured and os.path.exists(self.encrypted_db_path) |
| 321 | |
| 322 | return { |
| 323 | 'configured': configured, |
| 324 | 'authenticated': authenticated, |
| 325 | 'hw_match': hw_match, |
| 326 | 'recovery_codes_remaining': remaining_codes, |
| 327 | 'first_login': first_login, |
| 328 | 'db_ready': self._db_ready |
| 329 | } |
| 330 | |
| 331 | # ========================================================================= |
| 332 | # PUBLIC API - SETUP |
no test coverage detected