Download models.py from dn-scribe/attstore: direct link, hf CLI and curl.
- Browser
- Download file 28.7 kB
-
https://huggingface.co/spaces/dn-scribe/attstore/resolve/main/models.py
- Command line
-
hf download hf://spaces/dn-scribe/attstore/models.py
-
curl -L -o models.py https://huggingface.co/spaces/dn-scribe/attstore/resolve/main/models.py
28.7 kB
| from app import db | |
| from sqlalchemy import func | |
| from datetime import datetime | |
| from sqlalchemy import JSON, Text, Boolean, Integer, String, DateTime, ForeignKey, UniqueConstraint | |
| from sqlalchemy.orm import relationship | |
| import secrets | |
| from werkzeug.security import generate_password_hash, check_password_hash | |
| from sqlalchemy.ext.mutable import MutableDict | |
| def _default_attribute_mapping(): | |
| return { | |
| 'email': 'email', | |
| 'username': 'username', | |
| 'first_name': 'firstName', | |
| 'last_name': 'lastName' | |
| } | |
| class Tenant(db.Model): | |
| __tablename__ = 'tenants' | |
| id = db.Column(Integer, primary_key=True) | |
| name = db.Column(String(128), nullable=False) | |
| slug = db.Column(String(64), unique=True, nullable=False) | |
| description = db.Column(Text, nullable=True) | |
| active = db.Column(Boolean, default=True) | |
| allow_password_auth = db.Column(Boolean, default=True) | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| __table_args__ = ( | |
| db.Index('ix_tenants_slug', 'slug'), | |
| db.Index('ix_tenants_active', 'active'), | |
| ) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'name': self.name, | |
| 'slug': self.slug, | |
| 'description': self.description, | |
| 'active': self.active, | |
| 'allow_password_auth': self.allow_password_auth, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'updated_at': self.updated_at.isoformat() if self.updated_at else None, | |
| } | |
| class Badge(db.Model): | |
| __tablename__ = 'badges' | |
| id = db.Column(Integer, primary_key=True) | |
| name = db.Column(String(64), unique=True, nullable=False) | |
| description = db.Column(Text, nullable=True) | |
| owner_id = db.Column(Integer, ForeignKey('users.id'), nullable=True) # Null for global/admin badges | |
| is_global = db.Column(Boolean, default=False) | |
| last_modified = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| products = db.Column(String(255), nullable=True) # Product name pattern for LIKE query | |
| criteria = db.Column(Text, nullable=True) # SQL WHERE clause after user_id/product_key | |
| table = db.Column(String(64), default='policy_results') # Table to query (attestations or policy_results) | |
| positive = db.Column(Boolean, default=False) # If true, 0 is bad (red), >0 is good (green) | |
| visible = db.Column(Boolean, default=True) # New field: badge visibility | |
| owner = relationship('User', backref='badges', foreign_keys=[owner_id]) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'name': self.name, | |
| 'description': self.description, | |
| 'owner_id': self.owner_id, | |
| 'is_global': self.is_global, | |
| 'last_modified': self.last_modified.isoformat() if self.last_modified else None, | |
| 'products': self.products, | |
| 'criteria': self.criteria, | |
| 'table': self.table, | |
| 'positive': self.positive, | |
| 'visible': self.visible | |
| } | |
| from sqlalchemy import func | |
| from datetime import datetime, timedelta | |
| import secrets | |
| from sqlalchemy import JSON, Text, Boolean, Integer, String, DateTime, ForeignKey | |
| from sqlalchemy.orm import relationship | |
| from werkzeug.security import generate_password_hash, check_password_hash | |
| class User(db.Model): | |
| __tablename__ = 'users' | |
| id = db.Column(Integer, primary_key=True) | |
| username = db.Column(String(64), unique=True, nullable=False) | |
| email = db.Column(String(120), nullable=False) | |
| password_hash = db.Column(String(256), nullable=False) | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| is_active = db.Column(Boolean, default=True) | |
| is_admin = db.Column(Boolean, default=False) | |
| password_change_required = db.Column(Boolean, default=False) | |
| last_password_change = db.Column(DateTime, nullable=True) | |
| failed_login_attempts = db.Column(Integer, default=0) | |
| last_failed_login = db.Column(DateTime, nullable=True) | |
| last_successful_login = db.Column(DateTime, nullable=True) | |
| tenant_id = db.Column(Integer, ForeignKey('tenants.id'), nullable=True) | |
| tenant = relationship('Tenant', backref='users') | |
| def set_password(self, password): | |
| self.password_hash = generate_password_hash(password) | |
| self.last_password_change = datetime.utcnow() | |
| def check_password(self, password): | |
| return check_password_hash(self.password_hash, password) | |
| def record_login_success(self): | |
| """Record a successful login attempt""" | |
| self.failed_login_attempts = 0 | |
| self.last_successful_login = datetime.utcnow() | |
| def record_login_failure(self): | |
| """Record a failed login attempt""" | |
| self.failed_login_attempts += 1 | |
| self.last_failed_login = datetime.utcnow() | |
| # Only deactivate non-admin accounts after 50 consecutive failures | |
| if self.username != 'admin' and self.failed_login_attempts >= 50: | |
| self.is_active = False | |
| return True # Account was deactivated | |
| return False # Account was not deactivated | |
| __table_args__ = ( | |
| db.Index('ix_users_username', 'username'), | |
| db.Index('ix_users_is_active', 'is_active'), | |
| db.Index('ix_users_is_admin', 'is_admin'), | |
| db.Index('ix_users_tenant_id', 'tenant_id'), | |
| ) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'username': self.username, | |
| 'email': self.email, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'is_active': self.is_active, | |
| 'is_admin': self.is_admin, | |
| 'password_change_required': self.password_change_required, | |
| 'last_password_change': self.last_password_change.isoformat() if self.last_password_change else None, | |
| 'failed_login_attempts': self.failed_login_attempts, | |
| 'last_failed_login': self.last_failed_login.isoformat() if self.last_failed_login else None, | |
| 'last_successful_login': self.last_successful_login.isoformat() if self.last_successful_login else None, | |
| 'tenant_id': self.tenant_id, | |
| } | |
| class ApiKey(db.Model): | |
| __tablename__ = 'api_keys' | |
| id = db.Column(Integer, primary_key=True) | |
| key = db.Column(String(255), unique=True, nullable=False) | |
| name = db.Column(String(255)) # Optional description/name for the key | |
| user_id = db.Column(Integer, ForeignKey('users.id'), nullable=False) | |
| created_by = db.Column(Integer, ForeignKey('users.id'), nullable=False) | |
| expiration_date = db.Column(DateTime, nullable=True) # NULL means no expiration | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| is_active = db.Column(Boolean, default=True) | |
| # Relationships | |
| user = relationship("User", foreign_keys=[user_id], backref="api_keys") | |
| creator = relationship("User", foreign_keys=[created_by]) | |
| def generate_key(username): | |
| """Generate a secure API key in base64 format: username:secret""" | |
| import base64 | |
| secret = secrets.token_urlsafe(32) | |
| credentials = f"{username}:{secret}" | |
| return base64.b64encode(credentials.encode()).decode() | |
| def create_key(user_id, created_by, name=None, expiration_days=365): | |
| """Create a new API key with optional expiration""" | |
| from app import db | |
| # Get the user to extract username for key generation | |
| user = db.session.get(User, user_id) | |
| if not user: | |
| raise ValueError("User not found") | |
| key = ApiKey.generate_key(user.username) | |
| expiration_date = None | |
| if expiration_days is not None: | |
| expiration_date = datetime.utcnow() + timedelta(days=expiration_days) | |
| api_key = ApiKey() | |
| api_key.key = key | |
| api_key.name = name | |
| api_key.user_id = user_id | |
| api_key.created_by = created_by | |
| api_key.expiration_date = expiration_date | |
| return api_key | |
| def is_expired(self): | |
| """Check if the API key has expired""" | |
| if self.expiration_date is None: | |
| return False | |
| return datetime.utcnow() > self.expiration_date | |
| def is_valid(self): | |
| """Check if the API key is valid (active and not expired)""" | |
| return self.is_active and not self.is_expired() | |
| def get_client_credentials(self): | |
| """Extract client_id and client_secret from base64 encoded key""" | |
| try: | |
| import base64 | |
| decoded = base64.b64decode(self.key.encode()).decode() | |
| if ':' in decoded: | |
| client_id, client_secret = decoded.split(':', 1) | |
| return client_id, client_secret | |
| except: | |
| pass | |
| return None, None | |
| __table_args__ = ( | |
| db.Index('ix_api_keys_key', 'key'), | |
| db.Index('ix_api_keys_user_id', 'user_id'), | |
| db.Index('ix_api_keys_is_active', 'is_active'), | |
| db.Index('ix_api_keys_expiration_date', 'expiration_date'), | |
| ) | |
| def to_dict(self): | |
| client_id, client_secret = self.get_client_credentials() | |
| return { | |
| 'id': self.id, | |
| 'key': self.key, | |
| 'name': self.name, | |
| 'user_id': self.user_id, | |
| 'created_by': self.created_by, | |
| 'expiration_date': self.expiration_date.isoformat() if self.expiration_date else None, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'updated_at': self.updated_at.isoformat() if self.updated_at else None, | |
| 'is_active': self.is_active, | |
| 'is_expired': self.is_expired(), | |
| 'client_id': client_id, | |
| 'client_secret': client_secret | |
| } | |
| class ExternalIdentity(db.Model): | |
| __tablename__ = 'external_identities' | |
| __table_args__ = ( | |
| UniqueConstraint('provider', 'provider_id', 'external_id', name='uq_external_identity'), | |
| db.Index('ix_external_identities_user_id', 'user_id'), | |
| db.Index('ix_external_identities_tenant_id', 'tenant_id'), | |
| ) | |
| id = db.Column(Integer, primary_key=True) | |
| provider = db.Column(String(64), nullable=False) # e.g., 'saml' | |
| provider_id = db.Column(Integer, nullable=True) # SamlConfiguration.id for SAML | |
| external_id = db.Column(String(255), nullable=False) | |
| tenant_id = db.Column(Integer, ForeignKey('tenants.id'), nullable=True) | |
| user_id = db.Column(Integer, ForeignKey('users.id'), nullable=False) | |
| attributes = db.Column(MutableDict.as_mutable(JSON), default=dict) | |
| last_login_at = db.Column(DateTime, nullable=True) | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| user = relationship('User', backref='external_identities') | |
| tenant = relationship('Tenant', backref='external_identities') | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'provider': self.provider, | |
| 'provider_id': self.provider_id, | |
| 'external_id': self.external_id, | |
| 'tenant_id': self.tenant_id, | |
| 'user_id': self.user_id, | |
| 'attributes': self.attributes, | |
| 'last_login_at': self.last_login_at.isoformat() if self.last_login_at else None, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'updated_at': self.updated_at.isoformat() if self.updated_at else None, | |
| } | |
| class SamlConfiguration(db.Model): | |
| __tablename__ = 'saml_configurations' | |
| __table_args__ = ( | |
| db.Index('ix_saml_configurations_tenant_id', 'tenant_id'), | |
| db.Index('ix_saml_configurations_enabled', 'enabled'), | |
| UniqueConstraint('tenant_id', 'slug', name='uq_saml_tenant_slug'), | |
| ) | |
| id = db.Column(Integer, primary_key=True) | |
| tenant_id = db.Column(Integer, ForeignKey('tenants.id'), nullable=False) | |
| name = db.Column(String(128), nullable=False) | |
| slug = db.Column(String(64), unique=True, nullable=False) | |
| enabled = db.Column(Boolean, default=True) | |
| metadata_xml = db.Column(Text, nullable=False) | |
| idp_entity_id = db.Column(String(512), nullable=False) | |
| idp_sso_url = db.Column(String(512), nullable=False) | |
| idp_slo_url = db.Column(String(512), nullable=True) | |
| idp_certificate = db.Column(Text, nullable=False) | |
| sp_entity_id = db.Column(String(512), nullable=True) | |
| acs_url = db.Column(String(512), nullable=True) | |
| slo_url = db.Column(String(512), nullable=True) | |
| attribute_mapping = db.Column(MutableDict.as_mutable(JSON), default=_default_attribute_mapping) | |
| auto_provision_users = db.Column(Boolean, default=True) | |
| allow_idp_initiated = db.Column(Boolean, default=True) | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| created_by = db.Column(Integer, ForeignKey('users.id'), nullable=True) | |
| tenant = relationship('Tenant', backref='saml_configurations') | |
| creator = relationship('User', foreign_keys=[created_by]) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'tenant_id': self.tenant_id, | |
| 'name': self.name, | |
| 'slug': self.slug, | |
| 'enabled': self.enabled, | |
| 'idp_entity_id': self.idp_entity_id, | |
| 'idp_sso_url': self.idp_sso_url, | |
| 'idp_slo_url': self.idp_slo_url, | |
| 'sp_entity_id': self.sp_entity_id, | |
| 'acs_url': self.acs_url, | |
| 'slo_url': self.slo_url, | |
| 'attribute_mapping': self.attribute_mapping, | |
| 'auto_provision_users': self.auto_provision_users, | |
| 'allow_idp_initiated': self.allow_idp_initiated, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'updated_at': self.updated_at.isoformat() if self.updated_at else None, | |
| } | |
| class Attestation(db.Model): | |
| __tablename__ = 'attestations' | |
| id = db.Column(Integer, primary_key=True, doc="Primary key") | |
| key = db.Column(String(255), nullable=False, doc="Unique identifier for the attestation") # Unique identifier for the attestation | |
| target_name = db.Column(String(255), nullable=False, doc="Attestation Target name (e.g. image/file/repo name)") | |
| target_type = db.Column(String(100), nullable=False, doc="Target type (e.g. container, file, git, etc.)") | |
| content_type = db.Column(String(100), nullable=False, doc="Content type (e.g. cyclonedx-json)") | |
| context_type = db.Column(String(100), nullable=False, doc="Context type (e.g. local, github, gitlab, etc.)") | |
| tool = db.Column(String(100), doc="Tool that generated the attestation (usually valint)") | |
| sig_status = db.Column(String(50), default='unsigned', doc="Signature status (default 'unsigned')") | |
| deliverable = db.Column(Boolean, default=False, doc="Whether this attestation is of a deliverable artifact") | |
| # Context fields for deduplication | |
| product_key = db.Column(String(255), doc="Product key (name) for deduplication") | |
| product_version = db.Column(String(100), doc="Product version") | |
| labels = db.Column(JSON, doc="Labels as JSON array") # Store as JSON array | |
| # Storage information | |
| storage_path = db.Column(String(1000), doc="File path or S3 key for storage") # File path or S3 key | |
| storage_url = db.Column(String(3000), doc="Download URL for the attestation") # Download URL | |
| file_size = db.Column(Integer, doc="File size in bytes") | |
| # Context data | |
| context = db.Column(JSON, doc="Complete context stored as JSON") # Store complete context as JSON | |
| # Replacement tracking | |
| replaced_attestation_id = db.Column(Integer, ForeignKey('attestations.id'), nullable=True, doc="ID of the attestation that was replaced") | |
| replaced_by_attestation_id = db.Column(Integer, ForeignKey('attestations.id'), nullable=True, doc="ID of the attestation that replaced this one") | |
| # Metadata | |
| user_id = db.Column(Integer, ForeignKey('users.id'), doc="ID of the user who created the attestation") | |
| team_id = db.Column(Integer, doc="Team ID. Not in use yet.") | |
| job_ids = db.Column(JSON, doc="Job IDs as JSON array (backward compatibility)") # Store as JSON array | |
| pipeline_run = db.Column(Integer, doc="Pipeline run number (backward compatibility)") | |
| upload_pending = db.Column(Boolean, default=False, doc="True if upload is pending") # True if waiting for file upload | |
| # Timestamps | |
| created_at = db.Column(DateTime, default=datetime.utcnow, doc="Timestamp when the attestation was created") | |
| updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, doc="Timestamp when the attestation was last updated") | |
| deleted = db.Column(Boolean, default=False, doc="True if the attestation is deleted") | |
| __table_args__ = ( | |
| db.Index('ix_attestations_user_id_product_key', 'user_id', 'product_key'), | |
| ) | |
| # Relationships | |
| user = relationship("User", backref=db.backref("attestations", cascade="all, delete-orphan")) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'key': self.key, | |
| 'target_name': self.target_name, | |
| 'target_type': self.target_type, | |
| 'content_type': self.content_type, | |
| 'context_type': self.context_type, | |
| 'tool': self.tool, | |
| 'sig_status': self.sig_status, | |
| 'deliverable': self.deliverable, | |
| 'product_key': self.product_key, | |
| 'product_version': self.product_version, | |
| 'labels': self.labels, | |
| 'storage_url': self.storage_url, | |
| 'file_size': self.file_size, | |
| 'context': self.context, | |
| 'user_id': self.user_id, | |
| 'team_id': self.team_id, | |
| 'job_ids': self.job_ids, | |
| 'pipeline_run': self.pipeline_run, | |
| 'replaced_attestation_id': self.replaced_attestation_id, | |
| 'replaced_by_attestation_id': self.replaced_by_attestation_id, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'updated_at': self.updated_at.isoformat() if self.updated_at else None, | |
| 'deleted': self.deleted | |
| } | |
| class SystemLog(db.Model): | |
| __tablename__ = 'system_logs' | |
| __table_args__ = ( | |
| db.Index('ix_system_logs_timestamp', 'timestamp'), | |
| db.Index('ix_system_logs_user_id', 'user_id'), | |
| db.Index('ix_system_logs_severity', 'severity'), | |
| db.Index('ix_system_logs_event_type', 'event_type'), | |
| db.Index('ix_system_logs_app_name', 'app_name'), | |
| db.Index('ix_system_logs_hostname', 'hostname'), | |
| ) | |
| id = db.Column(Integer, primary_key=True) | |
| facility = db.Column(Integer, nullable=False) # RFC 5424 facility | |
| severity = db.Column(Integer, nullable=False, index=False) # RFC 5424 severity | |
| version = db.Column(Integer, default=1) # RFC 5424 version | |
| timestamp = db.Column(DateTime, default=datetime.utcnow, index=False) | |
| hostname = db.Column(String(255), index=False) | |
| app_name = db.Column(String(48), index=False) | |
| proc_id = db.Column(String(128)) | |
| msg_id = db.Column(String(32)) | |
| structured_data = db.Column(Text) # RFC 5424 structured data | |
| message = db.Column(Text) | |
| # Additional fields for internal use | |
| user_id = db.Column(Integer, ForeignKey('users.id'), nullable=True, index=False) | |
| source_ip = db.Column(String(45)) # IPv4 or IPv6 | |
| event_type = db.Column(String(50), index=False) # login, upload, download, etc. | |
| # Relationships | |
| user = relationship("User", backref="logs") | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'facility': self.facility, | |
| 'severity': self.severity, | |
| 'version': self.version, | |
| 'timestamp': self.timestamp.isoformat() if self.timestamp else None, | |
| 'hostname': self.hostname, | |
| 'app_name': self.app_name, | |
| 'proc_id': self.proc_id, | |
| 'msg_id': self.msg_id, | |
| 'structured_data': self.structured_data, | |
| 'message': self.message, | |
| 'user_id': self.user_id, | |
| 'source_ip': self.source_ip, | |
| 'event_type': self.event_type | |
| } | |
| def to_rfc5424(self): | |
| """Convert to RFC 5424 format""" | |
| priority = self.facility * 8 + self.severity | |
| timestamp_str = self.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ') if self.timestamp else '-' | |
| hostname = self.hostname or '-' | |
| app_name = self.app_name or '-' | |
| proc_id = self.proc_id or '-' | |
| msg_id = self.msg_id or '-' | |
| structured_data = self.structured_data or '-' | |
| message = self.message or '' | |
| return f"<{priority}>{self.version} {timestamp_str} {hostname} {app_name} {proc_id} {msg_id} {structured_data} {message}" | |
| class UploadSession(db.Model): | |
| __tablename__ = 'upload_sessions' | |
| id = db.Column(Integer, primary_key=True) | |
| session_id = db.Column(String(255), unique=True, nullable=False) | |
| user_id = db.Column(Integer, ForeignKey('users.id')) | |
| status = db.Column(String(50), default='pending') # pending, uploading, completed, failed | |
| file_name = db.Column(String(255)) | |
| file_size = db.Column(Integer) | |
| upload_url = db.Column(String(3000)) # Presigned URL for upload | |
| storage_path = db.Column(String(1000)) | |
| error_message = db.Column(Text) | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| completed_at = db.Column(DateTime) | |
| # Relationships | |
| user = relationship("User", backref="upload_sessions") | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'session_id': self.session_id, | |
| 'user_id': self.user_id, | |
| 'status': self.status, | |
| 'file_name': self.file_name, | |
| 'file_size': self.file_size, | |
| 'upload_url': self.upload_url, | |
| 'storage_path': self.storage_path, | |
| 'error_message': self.error_message, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'completed_at': self.completed_at.isoformat() if self.completed_at else None | |
| } | |
| class Webhook(db.Model): | |
| __tablename__ = 'webhooks' | |
| id = db.Column(Integer, primary_key=True) | |
| name = db.Column(String(255), nullable=False, unique=True) | |
| # Trigger type: "badge" or "attestation-condition" | |
| trigger_type = db.Column(String(64), nullable=False, default="badge") | |
| # Badge event trigger: store badge name and whether to trigger on non-zero count | |
| badge = db.Column(String(255), nullable=True) | |
| trigger_non_zero = db.Column(Boolean, default=True) | |
| # Attestation-condition: list of {field, value} pairs (ANDed) | |
| attestation_conditions = db.Column(JSON, nullable=True) | |
| url = db.Column(String(2000), nullable=False) | |
| secret = db.Column(String(255), nullable=True) | |
| created_by = db.Column(Integer, ForeignKey('users.id'), nullable=False) | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| is_active = db.Column(Boolean, default=True) | |
| headers = db.Column(db.Text, nullable=True) # JSON string | |
| content = db.Column(db.Text, nullable=True) # JSON string/template | |
| method = db.Column(String(10), nullable=False, default='POST') | |
| user = relationship("User", backref="webhooks") | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'name': self.name, | |
| 'trigger_type': self.trigger_type, | |
| 'badge': self.badge, | |
| 'trigger_non_zero': self.trigger_non_zero, | |
| 'attestation_conditions': self.attestation_conditions, | |
| 'url': self.url, | |
| 'secret': self.secret, | |
| 'created_by': self.created_by, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'is_active': self.is_active, | |
| 'headers': self.headers, | |
| 'content': self.content, | |
| 'method': self.method | |
| } | |
| # --- Policy Result and RuleResult Models --- | |
| class Product(db.Model): | |
| __tablename__ = 'products' | |
| id = db.Column(Integer, primary_key=True) | |
| product_key = db.Column(String(255), nullable=False) | |
| product_version = db.Column(String(255), nullable=False) | |
| user_id = db.Column(Integer, ForeignKey('users.id'), nullable=False) | |
| name = db.Column(String(255), nullable=True) | |
| description = db.Column(Text, nullable=True) | |
| product_metadata = db.Column(MutableDict.as_mutable(JSON), nullable=True) | |
| badges = db.Column(MutableDict.as_mutable(JSON), nullable=True) # Store badge data as JSON | |
| created_at = db.Column(DateTime, default=datetime.utcnow) | |
| updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| deleted = db.Column(Boolean, default=False) | |
| user = relationship("User", backref="products") | |
| __table_args__ = ( | |
| db.UniqueConstraint('user_id', 'product_key', 'product_version', name='uq_user_product_version'), | |
| db.Index('ix_products_product_key', 'product_key'), | |
| ) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'product_key': self.product_key, | |
| 'product_version': self.product_version, | |
| 'user_id': self.user_id, | |
| 'name': self.name, | |
| 'description': self.description, | |
| 'product_metadata': self.product_metadata, | |
| 'badges': self.badges, | |
| 'created_at': self.created_at.isoformat() if self.created_at else None, | |
| 'updated_at': self.updated_at.isoformat() if self.updated_at else None, | |
| 'deleted': self.deleted | |
| } | |
| class PolicyResult(db.Model): | |
| __tablename__ = 'policy_results' | |
| id = db.Column(Integer, primary_key=True, doc="Primary key") | |
| attestation_id = db.Column(Integer, ForeignKey('attestations.id'), nullable=False, doc="Related attestation ID") | |
| user_id = db.Column(Integer, ForeignKey('users.id'), nullable=True, doc="User ID who created the attestation") # User who created the attestation | |
| attestation_timestamp = db.Column(DateTime, nullable=False, doc="Timestamp of the attestation") | |
| initiative_id = db.Column(String(255), nullable=False, doc="Policy initiative ID") | |
| rule_result_id = db.Column(String(255), nullable=False, doc="Policy rule result ID") | |
| rule_id = db.Column(String(255), nullable=False, doc="Policy rule ID") | |
| rule_name = db.Column(String(255), nullable=True, doc="Name of the policy rule") | |
| rule_full_description = db.Column(Text, nullable=True, doc="Full description of the policy rule") | |
| result_kind = db.Column(String(64), nullable=True, doc="Type of the result") | |
| result_level = db.Column(String(64), nullable=True, doc="Level of the result") | |
| result_message = db.Column(Text, nullable=True, doc="Message for the result") | |
| rule_json = db.Column(JSON, nullable=False, doc="JSON of rule metadata") | |
| result_json = db.Column(JSON, nullable=False, doc="JSON of result metadata") | |
| product_key = db.Column(String(255), nullable=True, doc="Product key") | |
| product_version = db.Column(String(255), nullable=True, doc="Product version") | |
| deleted = db.Column(Boolean, default=False, doc="True if the policy result is deleted") | |
| attestation = relationship("Attestation", backref=db.backref("policy_results", cascade="all, delete-orphan")) | |
| user = relationship("User", backref=db.backref("policy_results", cascade="all, delete-orphan")) | |
| __table_args__ = ( | |
| db.Index('ix_policy_results_user_id_product_key', 'user_id', 'product_key'), | |
| db.Index('ix_policy_results_attestation_timestamp', 'attestation_timestamp'), | |
| ) | |
| def to_dict(self): | |
| return { | |
| 'id': self.id, | |
| 'attestation_id': self.attestation_id, | |
| 'user_id': self.user_id, | |
| 'attestation_timestamp': self.attestation_timestamp.isoformat() if self.attestation_timestamp else None, | |
| 'initiative_id': self.initiative_id, | |
| 'rule_result_id': self.rule_result_id, | |
| 'rule_id': self.rule_id, | |
| 'rule_name': self.rule_name, | |
| 'rule_full_description': self.rule_full_description, | |
| 'result_kind': self.result_kind, | |
| 'result_level': self.result_level, | |
| 'result_message': self.result_message, | |
| 'rule_json': self.rule_json, | |
| 'result_json': self.result_json, | |
| 'deleted': self.deleted | |
| } | |