Add CLI source code and update .gitignore

This commit is contained in:
2026-04-07 09:38:12 +08:00
parent 6ef2dddf3f
commit 9e17f1bf29
18 changed files with 2663 additions and 1 deletions

View File

@@ -0,0 +1,88 @@
"""
Session management for CodiMD CLI.
"""
import os
import json
from pathlib import Path
from typing import Optional, Dict, Any
from datetime import datetime, timedelta
import hashlib
class Session:
"""Session manager for CodiMD authentication."""
def __init__(self, config_dir: Path):
self.session_file = config_dir / "session.json"
self._session = self._load_session()
def _load_session(self) -> dict:
"""Load session from file."""
if self.session_file.exists():
with open(self.session_file, "r") as f:
return json.load(f)
return {}
def save_session(self):
"""Save session to file."""
with open(self.session_file, "w") as f:
json.dump(self._session, f, indent=2)
def is_authenticated(self) -> bool:
"""Check if user is authenticated."""
cookies = self._session.get("cookies", {})
if not cookies:
return False
# Check if session is expired (24 hours)
expires_at = self._session.get("expires_at")
if expires_at:
expire_time = datetime.fromisoformat(expires_at)
if datetime.now() > expire_time:
self.clear()
return False
return bool(cookies)
def set_cookies(self, cookies: Dict[str, str]):
"""Set session cookies."""
self._session["cookies"] = cookies
# Set expiration to 24 hours from now
self._session["expires_at"] = (
datetime.now() + timedelta(hours=24)
).isoformat()
self.save_session()
def get_cookies(self) -> Dict[str, str]:
"""Get session cookies."""
return self._session.get("cookies", {})
def set_user(self, user_data: Dict[str, Any]):
"""Set current user data."""
self._session["user"] = user_data
self.save_session()
def get_user(self) -> Optional[Dict[str, Any]]:
"""Get current user data."""
return self._session.get("user")
def clear(self):
"""Clear session data."""
self._session = {}
self.save_session()
@property
def user_id(self) -> Optional[str]:
"""Get current user ID."""
user = self.get_user()
return user.get("id") if user else None
@property
def username(self) -> Optional[str]:
"""Get current username."""
user = self.get_user()
if not user:
return None
# CodiMD returns name directly, not nested in profile
return user.get("name") or user.get("profile", {}).get("name")