from __future__ import annotations from datetime import datetime from enum import Enum from typing import Optional from sqlalchemy import DateTime, Enum as SAEnum, ForeignKey, Index, String, UniqueConstraint, text from sqlalchemy.dialects.mysql import BIGINT, TINYINT from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.db.base import Base class CredentialType(str, Enum): ACCESS_KEY = "ACCESS_KEY" ASSUME_ROLE = "ASSUME_ROLE" class AWSCredential(Base): __tablename__ = "aws_credentials" __table_args__ = ( UniqueConstraint("account_id", "name", name="uniq_credential_account_name"), Index("idx_credential_account", "account_id"), Index("idx_credential_active", "is_active"), ) id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(128), nullable=False) account_id: Mapped[str] = mapped_column(String(32), nullable=False) credential_type: Mapped[CredentialType] = mapped_column( SAEnum(CredentialType), nullable=False, server_default=text("'ACCESS_KEY'") ) access_key_id: Mapped[Optional[str]] = mapped_column(String(128)) secret_access_key: Mapped[Optional[str]] = mapped_column(String(256)) role_arn: Mapped[Optional[str]] = mapped_column(String(256)) external_id: Mapped[Optional[str]] = mapped_column(String(128)) default_region: Mapped[str] = mapped_column(String(32), nullable=False, server_default=text("'ap-northeast-1'")) is_active: Mapped[int] = mapped_column(TINYINT(1), nullable=False, server_default=text("1")) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False) updated_at: Mapped[datetime] = mapped_column( DateTime, server_default=text("CURRENT_TIMESTAMP"), onupdate=text("CURRENT_TIMESTAMP"), nullable=False ) customer_credentials: Mapped[list["CustomerCredential"]] = relationship( "CustomerCredential", back_populates="credential", passive_deletes=True ) instances: Mapped[list["Instance"]] = relationship("Instance", back_populates="credential", passive_deletes=True) class CustomerCredential(Base): __tablename__ = "customer_credentials" __table_args__ = ( UniqueConstraint("customer_id", "credential_id", name="uniq_customer_credential"), Index("idx_cc_customer", "customer_id"), Index("idx_cc_credential", "credential_id"), ) id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True) customer_id: Mapped[int] = mapped_column( ForeignKey("customers.id", ondelete="CASCADE", onupdate="CASCADE"), nullable=False ) credential_id: Mapped[int] = mapped_column( ForeignKey("aws_credentials.id", ondelete="CASCADE", onupdate="CASCADE"), nullable=False ) is_allowed: Mapped[int] = mapped_column(TINYINT(1), nullable=False, server_default=text("1")) created_at: Mapped[datetime] = mapped_column(DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False) updated_at: Mapped[datetime] = mapped_column( DateTime, server_default=text("CURRENT_TIMESTAMP"), onupdate=text("CURRENT_TIMESTAMP"), nullable=False ) customer: Mapped["Customer"] = relationship("Customer") credential: Mapped["AWSCredential"] = relationship( "AWSCredential", back_populates="customer_credentials", passive_deletes=True )