feat(platform): add audit logs and activity feed
This commit is contained in:
parent
92cb8d1286
commit
c816e9869d
34 changed files with 1592 additions and 43 deletions
104
backend/hermes/app/repositories/audit_repository.py
Normal file
104
backend/hermes/app/repositories/audit_repository.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Select, func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.audit import AuditLog
|
||||
|
||||
|
||||
class AuditRepository:
|
||||
@staticmethod
|
||||
def create(
|
||||
db: Session,
|
||||
*,
|
||||
actor_user_id: int | None,
|
||||
actor_username: str,
|
||||
action: str,
|
||||
entity_type: str,
|
||||
entity_id: int | None,
|
||||
entity_label: str,
|
||||
ip_address: str,
|
||||
user_agent: str,
|
||||
before_data: dict | list | None = None,
|
||||
after_data: dict | list | None = None,
|
||||
metadata: dict | list | None = None,
|
||||
) -> AuditLog:
|
||||
audit_log = AuditLog(
|
||||
actor_user_id=actor_user_id,
|
||||
actor_username=actor_username,
|
||||
action=action,
|
||||
entity_type=entity_type,
|
||||
entity_id=entity_id,
|
||||
entity_label=entity_label,
|
||||
ip_address=ip_address,
|
||||
user_agent=user_agent,
|
||||
before_data=before_data,
|
||||
after_data=after_data,
|
||||
metadata_data=metadata,
|
||||
)
|
||||
db.add(audit_log)
|
||||
db.commit()
|
||||
db.refresh(audit_log)
|
||||
return audit_log
|
||||
|
||||
@staticmethod
|
||||
def query(
|
||||
*,
|
||||
entity_type: str | None = None,
|
||||
actor_user_id: int | None = None,
|
||||
action: str | None = None,
|
||||
date_from: datetime | None = None,
|
||||
date_to: datetime | None = None,
|
||||
) -> Select[tuple[AuditLog]]:
|
||||
query = select(AuditLog)
|
||||
if entity_type:
|
||||
query = query.where(AuditLog.entity_type == entity_type)
|
||||
if actor_user_id is not None:
|
||||
query = query.where(AuditLog.actor_user_id == actor_user_id)
|
||||
if action:
|
||||
query = query.where(AuditLog.action == action)
|
||||
if date_from:
|
||||
query = query.where(AuditLog.created_at >= date_from)
|
||||
if date_to:
|
||||
query = query.where(AuditLog.created_at <= date_to)
|
||||
return query
|
||||
|
||||
@staticmethod
|
||||
def list(
|
||||
db: Session,
|
||||
*,
|
||||
page: int,
|
||||
page_size: int,
|
||||
entity_type: str | None = None,
|
||||
actor_user_id: int | None = None,
|
||||
action: str | None = None,
|
||||
date_from: datetime | None = None,
|
||||
date_to: datetime | None = None,
|
||||
) -> tuple[list[AuditLog], int]:
|
||||
base_query = AuditRepository.query(
|
||||
entity_type=entity_type,
|
||||
actor_user_id=actor_user_id,
|
||||
action=action,
|
||||
date_from=date_from,
|
||||
date_to=date_to,
|
||||
)
|
||||
total = db.scalar(select(func.count()).select_from(base_query.subquery())) or 0
|
||||
items = list(
|
||||
db.scalars(
|
||||
base_query
|
||||
.order_by(AuditLog.created_at.desc())
|
||||
.offset((page - 1) * page_size)
|
||||
.limit(page_size)
|
||||
)
|
||||
)
|
||||
return items, total
|
||||
|
||||
@staticmethod
|
||||
def latest(db: Session, limit: int = 10) -> list[AuditLog]:
|
||||
return list(
|
||||
db.scalars(
|
||||
select(AuditLog)
|
||||
.order_by(AuditLog.created_at.desc())
|
||||
.limit(limit)
|
||||
)
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue