Initialer Import des AssetManagers
This commit is contained in:
+478
@@ -0,0 +1,478 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Boolean, DateTime, ForeignKey, Index, Integer, JSON, String, Text, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from .database import Base
|
||||
|
||||
|
||||
class Category(Base):
|
||||
__tablename__ = "categories"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(100), unique=True, index=True)
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
image_path: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
|
||||
assets: Mapped[list["Asset"]] = relationship(back_populates="category")
|
||||
visible_fields: Mapped[list["CategoryField"]] = relationship(
|
||||
back_populates="category", cascade="all, delete-orphan", order_by="CategoryField.sort_order"
|
||||
)
|
||||
|
||||
|
||||
class FieldDefinition(Base):
|
||||
__tablename__ = "field_definitions"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
field_name: Mapped[str] = mapped_column(String(80), unique=True, index=True)
|
||||
label: Mapped[str] = mapped_column(String(120))
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
data_type: Mapped[str] = mapped_column(String(30), default="short_text")
|
||||
readonly: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
is_system: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
translation_key: Mapped[str | None] = mapped_column(String(180), nullable=True)
|
||||
searchable: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
filterable: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
chart_enabled: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
excel_import: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
excel_export: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
bulk_edit: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
is_default: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
list_width: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
category_links: Mapped[list["CategoryField"]] = relationship(back_populates="definition", cascade="all, delete-orphan")
|
||||
values: Mapped[list["AssetFieldValue"]] = relationship(back_populates="definition", cascade="all, delete-orphan")
|
||||
|
||||
|
||||
class CategoryField(Base):
|
||||
__tablename__ = "category_fields"
|
||||
__table_args__ = (UniqueConstraint("category_id", "field_name"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
category_id: Mapped[int] = mapped_column(ForeignKey("categories.id", ondelete="CASCADE"))
|
||||
field_name: Mapped[str] = mapped_column(String(80))
|
||||
label: Mapped[str] = mapped_column(String(100))
|
||||
field_definition_id: Mapped[int | None] = mapped_column(ForeignKey("field_definitions.id", ondelete="CASCADE"), nullable=True, index=True)
|
||||
active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
required: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
show_in_list: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
readonly: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
|
||||
category: Mapped[Category] = relationship(back_populates="visible_fields")
|
||||
definition: Mapped[FieldDefinition | None] = relationship(back_populates="category_links")
|
||||
|
||||
@property
|
||||
def effective_label(self) -> str:
|
||||
return self.definition.label if self.definition else self.label
|
||||
|
||||
@property
|
||||
def effective_readonly(self) -> bool:
|
||||
return bool(self.definition.readonly) if self.definition else bool(getattr(self, "readonly", False))
|
||||
|
||||
|
||||
class Asset(Base):
|
||||
__tablename__ = "assets"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
category_id: Mapped[int] = mapped_column(ForeignKey("categories.id"), index=True)
|
||||
asset_tag: Mapped[str | None] = mapped_column(String(100), unique=True, nullable=True, index=True)
|
||||
name: Mapped[str] = mapped_column(String(150), index=True)
|
||||
manufacturer: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
model: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
serial_number: Mapped[str | None] = mapped_column(String(150), nullable=True, index=True)
|
||||
status: Mapped[str | None] = mapped_column(String(60), nullable=True)
|
||||
assigned_to: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
assigned_on: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
||||
location: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
room_number: Mapped[str | None] = mapped_column(String(80), nullable=True, index=True)
|
||||
parent_asset_id: Mapped[int | None] = mapped_column(ForeignKey("assets.id", ondelete="SET NULL"), nullable=True, index=True)
|
||||
department: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
purchase_date: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
||||
warranty_until: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
||||
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
image_path: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
|
||||
hostname: Mapped[str | None] = mapped_column(String(150), nullable=True, index=True)
|
||||
operating_system: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
os_patch_level: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
mac_address: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
||||
ip_address: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
||||
cpu: Mapped[str | None] = mapped_column(String(200), nullable=True)
|
||||
memory_gb: Mapped[str | None] = mapped_column(String(40), nullable=True)
|
||||
storage_gb: Mapped[str | None] = mapped_column(String(40), nullable=True)
|
||||
storage_details: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
gpu_name: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
tpm_version: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
||||
memory_details: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
antivirus: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
mesh_group: Mapped[str | None] = mapped_column(String(180), nullable=True)
|
||||
mesh_mtype: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True)
|
||||
|
||||
mesh_node_id: Mapped[str | None] = mapped_column(String(180), unique=True, nullable=True, index=True)
|
||||
mesh_last_sync: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
mesh_last_seen: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
mesh_online: Mapped[bool | None] = mapped_column(Boolean, nullable=True, index=True)
|
||||
mesh_online_state: Mapped[str] = mapped_column(String(20), default="unknown", index=True)
|
||||
mesh_presence_updated_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
mesh_last_online_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
mesh_presence_source: Mapped[str | None] = mapped_column(String(40), nullable=True)
|
||||
mesh_sync_status: Mapped[str | None] = mapped_column(String(30), nullable=True, index=True)
|
||||
mesh_sync_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
mesh_conflicts: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
mesh_source_data: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
mesh_hardware_data: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
mesh_software_data: Mapped[list | dict] = mapped_column(JSON, default=list)
|
||||
mesh_inventory_updated_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
extra_data: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
category: Mapped[Category] = relationship(back_populates="assets")
|
||||
parent_asset: Mapped["Asset | None"] = relationship("Asset", remote_side="Asset.id", back_populates="child_assets", foreign_keys=[parent_asset_id])
|
||||
child_assets: Mapped[list["Asset"]] = relationship("Asset", back_populates="parent_asset", foreign_keys=[parent_asset_id])
|
||||
|
||||
|
||||
class AssetFieldValue(Base):
|
||||
__tablename__ = "asset_field_values"
|
||||
__table_args__ = (UniqueConstraint("asset_id", "field_definition_id"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
asset_id: Mapped[int] = mapped_column(ForeignKey("assets.id", ondelete="CASCADE"), index=True)
|
||||
field_definition_id: Mapped[int] = mapped_column(ForeignKey("field_definitions.id", ondelete="CASCADE"), index=True)
|
||||
value_text: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
value_number: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
||||
value_boolean: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||
value_date: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
||||
value_datetime: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
value_json: Mapped[dict | list | None] = mapped_column(JSON, nullable=True)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
asset: Mapped[Asset] = relationship()
|
||||
definition: Mapped[FieldDefinition] = relationship(back_populates="values")
|
||||
|
||||
|
||||
class MeshFieldMapping(Base):
|
||||
__tablename__ = "mesh_field_mappings"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
source_path: Mapped[str] = mapped_column(String(255), index=True)
|
||||
target_field_name: Mapped[str] = mapped_column(String(80), index=True)
|
||||
transform: Mapped[str] = mapped_column(String(40), default="raw")
|
||||
multi_value_mode: Mapped[str] = mapped_column(String(30), default="first")
|
||||
separator: Mapped[str] = mapped_column(String(20), default="\n")
|
||||
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
priority: Mapped[int] = mapped_column(Integer, default=0)
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
update_rule: Mapped[str] = mapped_column(String(30), default="fill_empty")
|
||||
is_system: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
|
||||
|
||||
class AssetHistory(Base):
|
||||
__tablename__ = "asset_history"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
asset_id: Mapped[int] = mapped_column(ForeignKey("assets.id", ondelete="CASCADE"), index=True)
|
||||
changed_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
|
||||
source: Mapped[str] = mapped_column(String(50), default="manual")
|
||||
changed_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
changes: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
|
||||
|
||||
class StatusOption(Base):
|
||||
__tablename__ = "status_options"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(60), unique=True, index=True)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
use_for_issue: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
use_for_return: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
|
||||
|
||||
class SyncRun(Base):
|
||||
__tablename__ = "sync_runs"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
source: Mapped[str] = mapped_column(String(50), default="meshcentral")
|
||||
started_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
finished_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
status: Mapped[str] = mapped_column(String(30), default="running")
|
||||
devices_found: Mapped[int] = mapped_column(Integer, default=0)
|
||||
created_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
updated_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
conflict_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
error_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
|
||||
|
||||
class ChartDefinition(Base):
|
||||
__tablename__ = "chart_definitions"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(150), unique=True, index=True)
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
chart_type: Mapped[str] = mapped_column(String(30), default="bar")
|
||||
group_field: Mapped[str] = mapped_column(String(80), default="category")
|
||||
stack_field: Mapped[str | None] = mapped_column(String(80), nullable=True)
|
||||
dashboard_visible: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
show_empty: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
max_items: Mapped[int] = mapped_column(Integer, default=12)
|
||||
sort_mode: Mapped[str] = mapped_column(String(30), default="count_desc")
|
||||
value_mode: Mapped[str] = mapped_column(String(30), default="raw")
|
||||
value_mappings: Mapped[list] = mapped_column(JSON, default=list)
|
||||
excluded_statuses: Mapped[list] = mapped_column(JSON, default=list)
|
||||
is_system: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
created_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
|
||||
class Language(Base):
|
||||
__tablename__ = "languages"
|
||||
|
||||
code: Mapped[str] = mapped_column(String(10), primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(80))
|
||||
native_name: Mapped[str] = mapped_column(String(80))
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
is_default: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
|
||||
|
||||
class Translation(Base):
|
||||
__tablename__ = "translations"
|
||||
__table_args__ = (UniqueConstraint("translation_key", "language_code"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
translation_key: Mapped[str] = mapped_column(String(180), index=True)
|
||||
language_code: Mapped[str] = mapped_column(ForeignKey("languages.code", ondelete="CASCADE"), index=True)
|
||||
text_value: Mapped[str] = mapped_column(Text)
|
||||
description: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
username: Mapped[str] = mapped_column(String(120), unique=True, index=True)
|
||||
display_name: Mapped[str | None] = mapped_column(String(180), nullable=True)
|
||||
email: Mapped[str | None] = mapped_column(String(180), nullable=True)
|
||||
password_hash: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
auth_source: Mapped[str] = mapped_column(String(30), default="local")
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
is_admin: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
is_protected: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
allowed_mesh_groups: Mapped[list] = mapped_column(JSON, default=list)
|
||||
asset_access_scopes: Mapped[list] = mapped_column(JSON, default=list)
|
||||
profile_department: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
profile_location: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
language_code: Mapped[str] = mapped_column(String(10), default="en")
|
||||
persist_browser_state: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
toast_position: Mapped[str] = mapped_column(String(30), default="top-right")
|
||||
toast_duration_seconds: Mapped[int] = mapped_column(Integer, default=6)
|
||||
theme_mode: Mapped[str] = mapped_column(String(20), default="light")
|
||||
last_login: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
|
||||
class JobDefinition(Base):
|
||||
__tablename__ = "job_definitions"
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(180), unique=True, index=True)
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
job_kind: Mapped[str] = mapped_column(String(30), default="script", index=True)
|
||||
configuration: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
system_key: Mapped[str | None] = mapped_column(String(120), unique=True, nullable=True, index=True)
|
||||
platform: Mapped[str] = mapped_column(String(30), default="windows", index=True)
|
||||
interpreter: Mapped[str] = mapped_column(String(30), default="powershell")
|
||||
source_type: Mapped[str] = mapped_column(String(30), default="inline")
|
||||
source_path: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
inline_script: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
arguments: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
timeout_seconds: Mapped[int] = mapped_column(Integer, default=300)
|
||||
success_codes: Mapped[str] = mapped_column(String(120), default="0")
|
||||
enabled: Mapped[bool] = mapped_column(Boolean, default=True, index=True)
|
||||
is_system: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
revision: Mapped[int] = mapped_column(Integer, default=1)
|
||||
created_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
updated_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
revisions: Mapped[list["JobDefinitionRevision"]] = relationship(back_populates="definition", cascade="all, delete-orphan", order_by="JobDefinitionRevision.revision.desc()")
|
||||
parameters: Mapped[list["JobDefinitionParameter"]] = relationship(back_populates="definition", cascade="all, delete-orphan", order_by="JobDefinitionParameter.sort_order")
|
||||
|
||||
|
||||
class JobDefinitionParameter(Base):
|
||||
__tablename__ = "job_definition_parameters"
|
||||
__table_args__ = (UniqueConstraint("definition_id", "parameter_key", name="uq_job_definition_parameter_key"),)
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
definition_id: Mapped[int] = mapped_column(ForeignKey("job_definitions.id", ondelete="CASCADE"), index=True)
|
||||
parameter_key: Mapped[str] = mapped_column(String(80))
|
||||
label: Mapped[str] = mapped_column(String(140))
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
data_type: Mapped[str] = mapped_column(String(30), default="text")
|
||||
default_value: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
required: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
definition: Mapped["JobDefinition"] = relationship(back_populates="parameters")
|
||||
|
||||
|
||||
class JobDefinitionAssetParameter(Base):
|
||||
__tablename__ = "job_definition_asset_parameters"
|
||||
__table_args__ = (UniqueConstraint("definition_parameter_id", "asset_id", name="uq_job_definition_asset_parameter"),)
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
definition_parameter_id: Mapped[int] = mapped_column(ForeignKey("job_definition_parameters.id", ondelete="CASCADE"), index=True)
|
||||
asset_id: Mapped[int] = mapped_column(ForeignKey("assets.id", ondelete="CASCADE"), index=True)
|
||||
value_text: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
updated_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
parameter: Mapped["JobDefinitionParameter"] = relationship()
|
||||
asset: Mapped["Asset"] = relationship()
|
||||
|
||||
|
||||
class JobDefinitionRevision(Base):
|
||||
__tablename__ = "job_definition_revisions"
|
||||
__table_args__ = (UniqueConstraint("definition_id", "revision", name="uq_job_definition_revision"),)
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
definition_id: Mapped[int] = mapped_column(ForeignKey("job_definitions.id", ondelete="CASCADE"), index=True)
|
||||
revision: Mapped[int] = mapped_column(Integer)
|
||||
snapshot: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
changed_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
definition: Mapped["JobDefinition"] = relationship(back_populates="revisions")
|
||||
|
||||
|
||||
class SoftwarePackage(Base):
|
||||
__tablename__ = "software_packages"
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(180), unique=True, index=True)
|
||||
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
package_type: Mapped[str] = mapped_column(String(40), default="command")
|
||||
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
is_system: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
command_windows: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
command_linux: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
command_macos: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
command_android: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
callback_timeout_minutes: Mapped[int] = mapped_column(Integer, default=30)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
parameters: Mapped[list["SoftwarePackageParameter"]] = relationship(back_populates="package", cascade="all, delete-orphan", order_by="SoftwarePackageParameter.sort_order")
|
||||
jobs: Mapped[list["SoftwareJob"]] = relationship(back_populates="package")
|
||||
|
||||
|
||||
class SoftwarePackageParameter(Base):
|
||||
__tablename__ = "software_package_parameters"
|
||||
__table_args__ = (UniqueConstraint("package_id", "name"),)
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
package_id: Mapped[int] = mapped_column(ForeignKey("software_packages.id", ondelete="CASCADE"), index=True)
|
||||
name: Mapped[str] = mapped_column(String(80))
|
||||
label: Mapped[str] = mapped_column(String(120))
|
||||
data_type: Mapped[str] = mapped_column(String(30), default="text")
|
||||
required: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
secret: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
default_value: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
validation_regex: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
||||
package: Mapped[SoftwarePackage] = relationship(back_populates="parameters")
|
||||
|
||||
|
||||
class SoftwareJob(Base):
|
||||
__tablename__ = "software_jobs"
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
asset_id: Mapped[int] = mapped_column(ForeignKey("assets.id", ondelete="CASCADE"), index=True)
|
||||
package_id: Mapped[int] = mapped_column(ForeignKey("software_packages.id"), index=True)
|
||||
status: Mapped[str] = mapped_column(String(30), default="created", index=True)
|
||||
job_type: Mapped[str] = mapped_column(String(50), default="software_inventory", index=True)
|
||||
action: Mapped[str] = mapped_column(String(30), default="run", index=True)
|
||||
priority: Mapped[int] = mapped_column(Integer, default=100, index=True)
|
||||
platform: Mapped[str] = mapped_column(String(30), default="unknown")
|
||||
parameters: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
result_data: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
attempt_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
max_attempts: Mapped[int] = mapped_column(Integer, default=1)
|
||||
scheduled_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, index=True)
|
||||
callback_token_hash: Mapped[str] = mapped_column(String(64), index=True)
|
||||
callback_expires_at: Mapped[datetime] = mapped_column(DateTime)
|
||||
callback_completed_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
command_preview: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
resolved_script: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
meshctrl_stdout: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
meshctrl_stderr: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
exit_code: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
log_text: Mapped[str] = mapped_column(Text, default="")
|
||||
created_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
|
||||
sent_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
started_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
finished_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
asset: Mapped[Asset] = relationship()
|
||||
package: Mapped[SoftwarePackage] = relationship(back_populates="jobs")
|
||||
events: Mapped[list["JobEvent"]] = relationship(back_populates="job", cascade="all, delete-orphan", order_by="JobEvent.created_at")
|
||||
|
||||
|
||||
class AssetJobState(Base):
|
||||
__tablename__ = "asset_job_states"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("asset_id", "state_key", name="uq_asset_job_state_asset_key"),
|
||||
Index("ix_asset_job_states_key_status", "state_key", "last_status"),
|
||||
Index("ix_asset_job_states_key_success", "state_key", "last_success_at"),
|
||||
Index("ix_asset_job_states_asset_key", "asset_id", "state_key"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
asset_id: Mapped[int] = mapped_column(ForeignKey("assets.id", ondelete="CASCADE"), index=True)
|
||||
state_key: Mapped[str] = mapped_column(String(120), index=True)
|
||||
job_type: Mapped[str] = mapped_column(String(50), index=True)
|
||||
job_definition_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True)
|
||||
definition_revision: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
last_success_revision: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
last_job_id: Mapped[int | None] = mapped_column(ForeignKey("software_jobs.id", ondelete="SET NULL"), nullable=True, index=True)
|
||||
last_status: Mapped[str] = mapped_column(String(30), default="created", index=True)
|
||||
last_status_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
|
||||
last_created_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
last_sent_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
last_started_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
last_completed_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
last_success_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, index=True)
|
||||
execution_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
asset: Mapped[Asset] = relationship()
|
||||
last_job: Mapped[SoftwareJob | None] = relationship()
|
||||
|
||||
|
||||
class JobEvent(Base):
|
||||
__tablename__ = "job_events"
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
job_id: Mapped[int] = mapped_column(ForeignKey("software_jobs.id", ondelete="CASCADE"), index=True)
|
||||
attempt: Mapped[int] = mapped_column(Integer, default=0)
|
||||
event_type: Mapped[str] = mapped_column(String(40), default="status", index=True)
|
||||
status: Mapped[str | None] = mapped_column(String(30), nullable=True, index=True)
|
||||
message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
created_by: Mapped[str | None] = mapped_column(String(150), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
|
||||
job: Mapped["SoftwareJob"] = relationship(back_populates="events")
|
||||
|
||||
|
||||
class InstalledSoftware(Base):
|
||||
__tablename__ = "installed_software"
|
||||
__table_args__ = (UniqueConstraint("asset_id", "name", "version", "publisher", "architecture", name="uq_installed_software_identity"),)
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
asset_id: Mapped[int] = mapped_column(ForeignKey("assets.id", ondelete="CASCADE"), index=True)
|
||||
name: Mapped[str] = mapped_column(String(300), index=True)
|
||||
version: Mapped[str] = mapped_column(String(160), default="")
|
||||
publisher: Mapped[str] = mapped_column(String(220), default="")
|
||||
architecture: Mapped[str] = mapped_column(String(40), default="")
|
||||
platform: Mapped[str] = mapped_column(String(40), default="unknown", index=True)
|
||||
install_date: Mapped[str | None] = mapped_column(String(40), nullable=True)
|
||||
source: Mapped[str] = mapped_column(String(50), default="meshcentral-inventory")
|
||||
first_seen_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
last_seen_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
|
||||
asset: Mapped[Asset] = relationship()
|
||||
Reference in New Issue
Block a user