""" Schedule 2 — 帳號檢查(每 3 分鐘) 檢查每個 active 帳號的: SSO使用者 / Mailbox / NC使用者 / Quota """ import logging from datetime import datetime from sqlalchemy.orm import Session from app.models.account import Account from app.models.result import AccountScheduleResult logger = logging.getLogger(__name__) def run_account_check(schedule_log_id: int, db: Session): from app.services.keycloak_client import KeycloakClient from app.services.mail_client import MailClient from app.services.nextcloud_client import NextcloudClient accounts = ( db.query(Account) .filter(Account.is_active == True) .all() ) kc = KeycloakClient() mail = MailClient() for account in accounts: tenant = account.tenant realm = tenant.keycloak_realm or tenant.code result = AccountScheduleResult( schedule_log_id=schedule_log_id, account_id=account.id, sso_account=account.sso_account, recorded_at=datetime.utcnow(), ) fail_reasons = [] # [1] SSO user check try: sso_uuid = kc.get_user_uuid(realm, account.sso_account) if sso_uuid: result.sso_result = True result.sso_uuid = sso_uuid if not account.sso_uuid: account.sso_uuid = sso_uuid else: sso_uuid = kc.create_user(realm, account.sso_account, account.email, account.default_password) result.sso_result = sso_uuid is not None result.sso_uuid = sso_uuid if sso_uuid and not account.sso_uuid: account.sso_uuid = sso_uuid result.sso_done_at = datetime.utcnow() except Exception as e: result.sso_result = False result.sso_done_at = datetime.utcnow() fail_reasons.append(f"sso: {e}") # [2] Mailbox check (skip if mail domain not ready) try: email = account.email or f"{account.sso_account}@{tenant.domain}" mb_exists = mail.mailbox_exists(email) if mb_exists: result.mailbox_result = True else: created = mail.create_mailbox(email, account.default_password, account.quota_limit) result.mailbox_result = created result.mailbox_done_at = datetime.utcnow() except Exception as e: result.mailbox_result = False result.mailbox_done_at = datetime.utcnow() fail_reasons.append(f"mailbox: {e}") # [3] NC user check try: nc = NextcloudClient(tenant.domain) nc_exists = nc.user_exists(account.sso_account) if nc_exists: result.nc_result = True else: created = nc.create_user(account.sso_account, account.default_password, account.quota_limit) result.nc_result = created result.nc_done_at = datetime.utcnow() except Exception as e: result.nc_result = False result.nc_done_at = datetime.utcnow() fail_reasons.append(f"nc: {e}") # [4] Quota try: nc = NextcloudClient(tenant.domain) result.quota_usage = nc.get_user_quota_used_gb(account.sso_account) except Exception as e: logger.warning(f"Quota check failed for {account.account_code}: {e}") if fail_reasons: result.fail_reason = "; ".join(fail_reasons) db.add(result) db.commit() db.flush() logger.info(f"Account check done: {len(accounts)} accounts processed")