110 lines
4.1 KiB
Python
110 lines
4.1 KiB
Python
from typing import Optional
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy import or_, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from models.models import Account, AutoReplyRule, MessageLog, ReceivedMessageLog, SystemLog, User
|
|
from .roles import is_admin
|
|
|
|
|
|
async def get_owned_account(
|
|
db: AsyncSession,
|
|
user: User,
|
|
account_id: int,
|
|
*,
|
|
write: bool = False,
|
|
) -> Account:
|
|
result = await db.execute(select(Account).where(Account.id == account_id))
|
|
account = result.scalar_one_or_none()
|
|
if not account:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="账号不存在")
|
|
if is_admin(user.role):
|
|
return account
|
|
if account.owner_id != user.id:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="无权访问该账号")
|
|
if write and user.role == "viewer":
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="只读用户无法修改")
|
|
return account
|
|
|
|
|
|
def accounts_for_user(user: User):
|
|
stmt = select(Account)
|
|
if not is_admin(user.role):
|
|
stmt = stmt.where(Account.owner_id == user.id)
|
|
return stmt
|
|
|
|
|
|
async def owned_account_ids(db: AsyncSession, user: User) -> Optional[set[int]]:
|
|
if is_admin(user.role):
|
|
return None
|
|
result = await db.execute(select(Account.id).where(Account.owner_id == user.id))
|
|
return {row[0] for row in result.all()}
|
|
|
|
|
|
def logs_for_user(user: User, account_id: Optional[int] = None):
|
|
stmt = select(MessageLog)
|
|
if account_id is not None:
|
|
stmt = stmt.where(MessageLog.account_id == account_id)
|
|
if not is_admin(user.role):
|
|
owned = select(Account.id).where(Account.owner_id == user.id)
|
|
stmt = stmt.where(MessageLog.account_id.in_(owned))
|
|
return stmt
|
|
|
|
|
|
def received_logs_for_user(user: User, account_id: Optional[int] = None):
|
|
stmt = select(ReceivedMessageLog)
|
|
if account_id is not None:
|
|
stmt = stmt.where(ReceivedMessageLog.account_id == account_id)
|
|
if not is_admin(user.role):
|
|
owned = select(Account.id).where(Account.owner_id == user.id)
|
|
stmt = stmt.where(ReceivedMessageLog.account_id.in_(owned))
|
|
return stmt
|
|
|
|
|
|
def rules_for_user(user: User, account_id: Optional[int] = None):
|
|
stmt = select(AutoReplyRule)
|
|
if account_id is not None:
|
|
stmt = stmt.where(AutoReplyRule.account_id == account_id)
|
|
if is_admin(user.role):
|
|
return stmt
|
|
owned = select(Account.id).where(Account.owner_id == user.id)
|
|
return stmt.where(AutoReplyRule.account_id.in_(owned))
|
|
|
|
|
|
async def get_accessible_rule(db: AsyncSession, user: User, rule_id: int, *, write: bool = False) -> AutoReplyRule:
|
|
result = await db.execute(select(AutoReplyRule).where(AutoReplyRule.id == rule_id))
|
|
rule = result.scalar_one_or_none()
|
|
if not rule:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="规则不存在")
|
|
|
|
if is_admin(user.role):
|
|
if write and user.role == "viewer":
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="只读用户无法修改")
|
|
return rule
|
|
|
|
if rule.account_id is None:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="无权访问全局规则")
|
|
|
|
account = await get_owned_account(db, user, rule.account_id, write=write)
|
|
if rule.owner_id and rule.owner_id != user.id and account.owner_id != user.id:
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="无权访问该规则")
|
|
if write and user.role == "viewer":
|
|
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="只读用户无法修改")
|
|
return rule
|
|
|
|
|
|
def system_logs_for_user(user: User, account_id: Optional[int] = None):
|
|
stmt = select(SystemLog)
|
|
if account_id is not None:
|
|
stmt = stmt.where(SystemLog.account_id == account_id)
|
|
if not is_admin(user.role):
|
|
owned = select(Account.id).where(Account.owner_id == user.id)
|
|
stmt = stmt.where(
|
|
or_(
|
|
SystemLog.account_id.in_(owned),
|
|
SystemLog.account_id.is_(None),
|
|
)
|
|
)
|
|
return stmt
|