fix: correct audit event names, attachment deletion, redirect safety, and add account deactivation check
- Fix audit event names in CLI prune/clear commands from `cli.seo.*` to `cli.seo_meta.*`
- Refactor `_delete_attachment_file` to accept full attachment dict instead of storage_path string, using directory and stored_name fields with ATTACHMENTS_DIR
- Add `safe_next` validation for referer header in validation error redirect and media redirect
- Add `is_active` check in login router to reject deactivated accounts with "Account is deactivated" error
- Replace raw `request.headers.get("Referer")` with `redirect_back()` utility in bookmarks, polls, reactions, and votes routers
- Move `mark_conversation_read` call from `get_conversation_messages` to `messages_page` to avoid side effects during message retrieval
- Fix poll audit link to use `option.get("label")` instead of `option.get("text")`
- Add `VOTABLE` set validation in votes router to reject invalid target types with 400 response
- Strip control characters (0x00-0x20) from URLs in `_safe_url` instead of simple strip
- Add `__getattr__` fallback in services `__init__.py` for dynamic attribute access
This commit is contained in:
@@ -81,7 +81,12 @@ class VirtualToolStore:
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
}
|
||||
self._table.insert(record)
|
||||
existing = self._table.find_one(name=record["name"], **self._scope)
|
||||
if existing:
|
||||
record["id"] = existing["id"]
|
||||
self._table.update(record, ["id"])
|
||||
else:
|
||||
self._table.insert(record)
|
||||
logger.info(
|
||||
"Virtual tool created name=%s owner=%s/%s",
|
||||
record.get("name"),
|
||||
@@ -91,8 +96,11 @@ class VirtualToolStore:
|
||||
return record
|
||||
|
||||
def update(self, name: str, changes: dict[str, Any]) -> None:
|
||||
changes = {**changes, "name": name, **self._scope, "updated_at": _now_iso()}
|
||||
self._table.update(changes, ["name", "owner_kind", "owner_id"])
|
||||
row = self._table.find_one(name=name, deleted_at=None, **self._scope)
|
||||
if not row:
|
||||
return
|
||||
changes = {**changes, "id": row["id"], "updated_at": _now_iso()}
|
||||
self._table.update(changes, ["id"])
|
||||
logger.debug("Virtual tool updated name=%s changes=%s", name, list(changes))
|
||||
|
||||
def delete(self, name: str) -> bool:
|
||||
@@ -101,12 +109,11 @@ class VirtualToolStore:
|
||||
return False
|
||||
self._table.update(
|
||||
{
|
||||
"name": name,
|
||||
"id": row["id"],
|
||||
"deleted_at": _now_iso(),
|
||||
"deleted_by": f"{self._owner_kind}:{self._owner_id}",
|
||||
**self._scope,
|
||||
},
|
||||
["name", "owner_kind", "owner_id"],
|
||||
["id"],
|
||||
)
|
||||
logger.info("Virtual tool soft-deleted name=%s", name)
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user