refactor: switch Wiki.js client to API token authentication
Replace username/password login flow with simpler API token auth: - Use WIKI_GRAPHQL_API environment variable for JWT token - Remove login() method and session management - Add list_pages() method for fetching all pages - Keep legacy auth fields in config for backwards compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,96 +20,31 @@ class WikiJSClient:
|
||||
Wiki.js GraphQL API client.
|
||||
|
||||
Documentation: https://docs.requarks.io/dev/api
|
||||
Authentication: Username/password login to get user-specific JWT token
|
||||
Authentication: API token (JWT) generated from Wiki.js admin panel
|
||||
"""
|
||||
|
||||
def __init__(self, base_url: str, username: str, password: str):
|
||||
def __init__(self, base_url: str, api_token: str):
|
||||
"""
|
||||
Initialize Wiki.js client.
|
||||
|
||||
Args:
|
||||
base_url: Wiki.js base URL (e.g., "http://wiki:3000")
|
||||
username: Wiki.js username (e.g., "librarian@schweitz.net")
|
||||
password: Wiki.js password
|
||||
api_token: Wiki.js API token (JWT from admin panel)
|
||||
"""
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.graphql_url = f"{self.base_url}/graphql"
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.jwt_token: Optional[str] = None
|
||||
self.api_token = api_token
|
||||
self.client = httpx.AsyncClient(timeout=30.0)
|
||||
logger.info(f"Initialized Wiki.js client: {base_url} (user: {username})")
|
||||
logger.info(f"Initialized Wiki.js client: {base_url} (using API token)")
|
||||
|
||||
async def close(self):
|
||||
"""Close HTTP client"""
|
||||
await self.client.aclose()
|
||||
|
||||
async def login(self) -> bool:
|
||||
"""
|
||||
Authenticate with Wiki.js using username/password.
|
||||
|
||||
Returns:
|
||||
True if login successful, False otherwise
|
||||
"""
|
||||
login_mutation = """
|
||||
mutation Login($username: String!, $password: String!, $strategy: String!) {
|
||||
authentication {
|
||||
login(username: $username, password: $password, strategy: $strategy) {
|
||||
responseResult {
|
||||
succeeded
|
||||
errorCode
|
||||
message
|
||||
}
|
||||
jwt
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
variables = {
|
||||
"username": self.username,
|
||||
"password": self.password,
|
||||
"strategy": "local"
|
||||
}
|
||||
|
||||
try:
|
||||
response = await self.client.post(
|
||||
self.graphql_url,
|
||||
headers={"Content-Type": "application/json"},
|
||||
json={"query": login_mutation, "variables": variables}
|
||||
)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
if "errors" in result:
|
||||
logger.error(f"Login failed: {result['errors']}")
|
||||
return False
|
||||
|
||||
login_result = result.get("data", {}).get("authentication", {}).get("login", {})
|
||||
response_result = login_result.get("responseResult", {})
|
||||
|
||||
if not response_result.get("succeeded"):
|
||||
logger.error(f"Login failed: {response_result.get('message')}")
|
||||
return False
|
||||
|
||||
self.jwt_token = login_result.get("jwt")
|
||||
if not self.jwt_token:
|
||||
logger.error("Login succeeded but no JWT token received")
|
||||
return False
|
||||
|
||||
logger.info(f"Successfully authenticated as {self.username}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Login failed: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
async def _ensure_authenticated(self):
|
||||
"""Ensure we have a valid JWT token, login if needed."""
|
||||
if not self.jwt_token:
|
||||
success = await self.login()
|
||||
if not success:
|
||||
raise Exception("Failed to authenticate with Wiki.js")
|
||||
def _ensure_authenticated(self):
|
||||
"""Verify API token is configured."""
|
||||
if not self.api_token:
|
||||
raise Exception("Wiki.js API token not configured")
|
||||
|
||||
async def _execute_query(
|
||||
self,
|
||||
@@ -129,8 +64,8 @@ class WikiJSClient:
|
||||
Raises:
|
||||
Exception: If query fails or returns errors
|
||||
"""
|
||||
# Ensure we're authenticated before making requests
|
||||
await self._ensure_authenticated()
|
||||
# Ensure API token is configured
|
||||
self._ensure_authenticated()
|
||||
|
||||
payload = {
|
||||
"query": query,
|
||||
@@ -138,7 +73,7 @@ class WikiJSClient:
|
||||
}
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.jwt_token}",
|
||||
"Authorization": f"Bearer {self.api_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user