from datetime import datetime from typing import Any from flask_login import UserMixin from werkzeug.security import check_password_hash, generate_password_hash from app.extensions import db, login_manager class TimestampMixin: created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class User(UserMixin, TimestampMixin, db.Model): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, nullable=False) password_hash = db.Column(db.String(255), nullable=False) email = db.Column(db.String(128)) role = db.Column(db.String(32)) is_active = db.Column(db.Boolean, default=True) def set_password(self, password: str) -> None: self.password_hash = generate_password_hash(password) def check_password(self, password: str) -> bool: return check_password_hash(self.password_hash, password) @property def is_authenticated(self) -> bool: # type: ignore[override] return True def get_id(self) -> str: # type: ignore[override] return str(self.id) @login_manager.user_loader def load_user(user_id: str) -> Any: return User.query.get(int(user_id)) class ApiConfig(TimestampMixin, db.Model): __tablename__ = "api_configs" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), nullable=False) description = db.Column(db.Text) url = db.Column(db.String(512), nullable=False) http_method = db.Column(db.String(10), nullable=False, default="GET") headers = db.Column(db.Text) query_params = db.Column(db.Text) body = db.Column(db.Text) enabled = db.Column(db.Boolean, default=True) schedule_type = db.Column(db.String(32), nullable=False, default="cron") schedule_expression = db.Column(db.String(128), nullable=False, default="0 10 * * *") timeout_seconds = db.Column(db.Integer, default=30) retry_times = db.Column(db.Integer, default=0) retry_interval_seconds = db.Column(db.Integer, default=3) created_by = db.Column(db.Integer, db.ForeignKey("users.id")) creator = db.relationship("User", backref="api_configs") def job_id(self) -> str: return f"api_job_{self.id}" class ApiCallLog(TimestampMixin, db.Model): __tablename__ = "api_call_logs" id = db.Column(db.Integer, primary_key=True) api_id = db.Column(db.Integer, db.ForeignKey("api_configs.id"), nullable=False) request_time = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) response_time = db.Column(db.DateTime) success = db.Column(db.Boolean, default=False) http_status_code = db.Column(db.Integer) error_message = db.Column(db.Text) response_body = db.Column(db.Text) duration_ms = db.Column(db.Integer) api = db.relationship("ApiConfig", backref="call_logs")