fix: add input validation, retry limit, code formatting, and exclude i18n from secret detection

This commit is contained in:
Differ 2025-12-05 09:58:49 +08:00
parent 6b1b8d0f2e
commit 500bc60d02
3 changed files with 38 additions and 17 deletions

View file

@ -35,7 +35,8 @@ repos:
.*pnpm-lock\.yaml| .*pnpm-lock\.yaml|
.*alembic\.ini| .*alembic\.ini|
.*alembic/versions/.*\.py| .*alembic/versions/.*\.py|
.*\.mdx$ .*\.mdx$|
.*/messages/.*\.json$
)$ )$
# Python Backend Hooks (surfsense_backend) - Using Ruff for linting and formatting # Python Backend Hooks (surfsense_backend) - Using Ruff for linting and formatting

View file

@ -42,9 +42,7 @@ class BookStackConnector:
self.token_secret = token_secret self.token_secret = token_secret
self._last_request_time = 0.0 self._last_request_time = 0.0
def set_credentials( def set_credentials(self, base_url: str, token_id: str, token_secret: str) -> None:
self, base_url: str, token_id: str, token_secret: str
) -> None:
""" """
Set the BookStack credentials. Set the BookStack credentials.
@ -52,7 +50,17 @@ class BookStackConnector:
base_url: BookStack instance base URL base_url: BookStack instance base URL
token_id: BookStack API Token ID token_id: BookStack API Token ID
token_secret: BookStack API Token Secret token_secret: BookStack API Token Secret
Raises:
ValueError: If any required credential is missing or invalid
""" """
if not base_url or not isinstance(base_url, str):
raise ValueError("base_url must be a non-empty string")
if not token_id or not isinstance(token_id, str):
raise ValueError("token_id must be a non-empty string")
if not token_secret or not isinstance(token_secret, str):
raise ValueError("token_secret must be a non-empty string")
self.base_url = base_url.rstrip("/") self.base_url = base_url.rstrip("/")
self.token_id = token_id self.token_id = token_id
self.token_secret = token_secret self.token_secret = token_secret
@ -86,11 +94,15 @@ class BookStackConnector:
time.sleep(self.REQUEST_INTERVAL - elapsed) time.sleep(self.REQUEST_INTERVAL - elapsed)
self._last_request_time = time.time() self._last_request_time = time.time()
# Maximum retries for rate limit errors
MAX_RATE_LIMIT_RETRIES = 3
def make_api_request( def make_api_request(
self, self,
endpoint: str, endpoint: str,
params: dict[str, Any] | None = None, params: dict[str, Any] | None = None,
raw_response: bool = False, raw_response: bool = False,
_retry_count: int = 0,
) -> dict[str, Any] | str: ) -> dict[str, Any] | str:
""" """
Make a request to the BookStack API. Make a request to the BookStack API.
@ -128,9 +140,17 @@ class BookStackConnector:
except requests.exceptions.HTTPError as e: except requests.exceptions.HTTPError as e:
if e.response.status_code == 429: if e.response.status_code == 429:
logger.warning("Rate limit exceeded, waiting 60 seconds...") if _retry_count >= self.MAX_RATE_LIMIT_RETRIES:
raise Exception(
f"BookStack API rate limit exceeded after {self.MAX_RATE_LIMIT_RETRIES} retries"
) from e
logger.warning(
f"Rate limit exceeded, waiting 60 seconds... (retry {_retry_count + 1}/{self.MAX_RATE_LIMIT_RETRIES})"
)
time.sleep(60) time.sleep(60)
return self.make_api_request(endpoint, params, raw_response) return self.make_api_request(
endpoint, params, raw_response, _retry_count + 1
)
raise Exception(f"BookStack API request failed: {e!s}") from e raise Exception(f"BookStack API request failed: {e!s}") from e
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
raise Exception(f"BookStack API request failed: {e!s}") from e raise Exception(f"BookStack API request failed: {e!s}") from e

View file

@ -87,7 +87,11 @@ async def index_bookstack_pages(
bookstack_token_id = connector.config.get("BOOKSTACK_TOKEN_ID") bookstack_token_id = connector.config.get("BOOKSTACK_TOKEN_ID")
bookstack_token_secret = connector.config.get("BOOKSTACK_TOKEN_SECRET") bookstack_token_secret = connector.config.get("BOOKSTACK_TOKEN_SECRET")
if not bookstack_base_url or not bookstack_token_id or not bookstack_token_secret: if (
not bookstack_base_url
or not bookstack_token_id
or not bookstack_token_secret
):
await task_logger.log_task_failure( await task_logger.log_task_failure(
log_entry, log_entry,
f"BookStack credentials not found in connector config for connector {connector_id}", f"BookStack credentials not found in connector config for connector {connector_id}",
@ -196,9 +200,7 @@ async def index_bookstack_pages(
page_id, use_markdown=True page_id, use_markdown=True
) )
except Exception as e: except Exception as e:
logger.warning( logger.warning(f"Failed to fetch content for page {page_name}: {e}")
f"Failed to fetch content for page {page_name}: {e}"
)
skipped_pages.append(f"{page_name} (content fetch error)") skipped_pages.append(f"{page_name} (content fetch error)")
documents_skipped += 1 documents_skipped += 1
continue continue
@ -275,7 +277,9 @@ async def index_bookstack_pages(
full_content, user_llm, summary_metadata full_content, user_llm, summary_metadata
) )
else: else:
summary_content = f"BookStack Page: {page_name}\n\nBook ID: {book_id}\n\n" summary_content = (
f"BookStack Page: {page_name}\n\nBook ID: {book_id}\n\n"
)
if page_content: if page_content:
content_preview = page_content[:1000] content_preview = page_content[:1000]
if len(page_content) > 1000: if len(page_content) > 1000:
@ -299,9 +303,7 @@ async def index_bookstack_pages(
existing_document.chunks = chunks existing_document.chunks = chunks
documents_indexed += 1 documents_indexed += 1
logger.info( logger.info(f"Successfully updated BookStack page {page_name}")
f"Successfully updated BookStack page {page_name}"
)
continue continue
# Document doesn't exist - create new one # Document doesn't exist - create new one
@ -388,9 +390,7 @@ async def index_bookstack_pages(
f"Final commit: Total {documents_indexed} BookStack pages processed" f"Final commit: Total {documents_indexed} BookStack pages processed"
) )
await session.commit() await session.commit()
logger.info( logger.info("Successfully committed all BookStack document changes to database")
"Successfully committed all BookStack document changes to database"
)
# Log success # Log success
await task_logger.log_task_success( await task_logger.log_task_success(