Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,206 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import Any
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from sqlalchemy import select
|
||||
|
||||
from packages.hub_clients import (
|
||||
BootstrapHandle,
|
||||
ClientConfig,
|
||||
ClientKind,
|
||||
ClientRecord,
|
||||
ClientStatus,
|
||||
generate_config,
|
||||
)
|
||||
from services.control_api.persistence.models import (
|
||||
ClientBindingRow,
|
||||
ClientRow,
|
||||
EnvironmentRow,
|
||||
ProjectRow,
|
||||
VirtualServerRow,
|
||||
WorkspaceRow,
|
||||
)
|
||||
|
||||
|
||||
class PersistentClientService:
|
||||
"""Database-backed production lifecycle shared by the control API and dataplane."""
|
||||
|
||||
def __init__(self, sessions: Any, *, issuer: str, public_host: str) -> None:
|
||||
self.sessions = sessions
|
||||
self.issuer = issuer
|
||||
self.public_host = public_host
|
||||
|
||||
@staticmethod
|
||||
def _record(row: ClientRow) -> ClientRecord:
|
||||
metadata = row.record_metadata if isinstance(row.record_metadata, dict) else {}
|
||||
client_status = {
|
||||
"active": ClientStatus.ENABLED,
|
||||
"disabled": ClientStatus.DISABLED,
|
||||
"pending": ClientStatus.PENDING,
|
||||
"revoked": ClientStatus.REVOKED,
|
||||
}.get(row.status, ClientStatus.DISABLED)
|
||||
return ClientRecord(
|
||||
id=row.id,
|
||||
name=str(metadata.get("name", row.subject)),
|
||||
project=str(metadata.get("project", "unknown")),
|
||||
environment=str(metadata.get("environment", "prod")),
|
||||
kind=ClientKind(str(metadata.get("kind", ClientKind.NATIVE_2026.value))),
|
||||
status=client_status,
|
||||
credential_reference=str(
|
||||
metadata.get("credentialReference", f"authentik://mcp-client/{row.id}")
|
||||
),
|
||||
created_at=row.created_at,
|
||||
last_seen_at=row.last_seen_at,
|
||||
disabled_at=metadata.get("disabledAt"),
|
||||
revoked_at=row.revoked_at,
|
||||
)
|
||||
|
||||
def create(
|
||||
self, *, name: str, project: str, environment: str, kind: ClientKind
|
||||
) -> tuple[ClientRecord, BootstrapHandle, ClientConfig]:
|
||||
now = datetime.now(UTC)
|
||||
client_id = uuid4()
|
||||
bootstrap = BootstrapHandle(
|
||||
client_id=client_id,
|
||||
reference=f"authentik-bootstrap://{uuid4()}",
|
||||
expires_at=now + timedelta(minutes=5),
|
||||
)
|
||||
credential_reference = f"authentik://mcp-client/{client_id}"
|
||||
with self.sessions() as session, session.begin():
|
||||
workspace_id = session.scalar(
|
||||
select(WorkspaceRow.id).where(WorkspaceRow.slug == "itworx")
|
||||
)
|
||||
if workspace_id is None:
|
||||
raise ValueError("client workspace is not initialized")
|
||||
project_row = session.scalar(
|
||||
select(ProjectRow).where(
|
||||
ProjectRow.workspace_id == workspace_id,
|
||||
ProjectRow.slug == project,
|
||||
ProjectRow.status == "active",
|
||||
)
|
||||
)
|
||||
if project_row is None:
|
||||
raise ValueError("client project is not registered")
|
||||
environment_row = session.scalar(
|
||||
select(EnvironmentRow).where(
|
||||
EnvironmentRow.workspace_id == workspace_id,
|
||||
EnvironmentRow.project_id == project_row.id,
|
||||
EnvironmentRow.name == environment,
|
||||
EnvironmentRow.status == "active",
|
||||
)
|
||||
)
|
||||
if environment_row is None:
|
||||
raise ValueError("client environment is not registered")
|
||||
server = session.scalar(
|
||||
select(VirtualServerRow).where(
|
||||
VirtualServerRow.workspace_id == workspace_id,
|
||||
VirtualServerRow.project_id == project_row.id,
|
||||
VirtualServerRow.environment_id == environment_row.id,
|
||||
VirtualServerRow.enabled.is_(True),
|
||||
)
|
||||
)
|
||||
if server is None:
|
||||
raise ValueError("client environment has no enabled virtual server")
|
||||
row = ClientRow(
|
||||
id=client_id,
|
||||
workspace_id=workspace_id,
|
||||
subject=f"itworx-mcp-client-{client_id}",
|
||||
issuer=self.issuer,
|
||||
status="pending",
|
||||
record_metadata={
|
||||
"managedBy": "runtime-onboarding",
|
||||
"name": name,
|
||||
"project": project,
|
||||
"environment": environment,
|
||||
"kind": kind.value,
|
||||
"credentialReference": credential_reference,
|
||||
"bootstrapReference": bootstrap.reference,
|
||||
"bootstrapExpiresAt": bootstrap.expires_at.isoformat(),
|
||||
"operatorDisabled": False,
|
||||
},
|
||||
)
|
||||
session.add(row)
|
||||
session.flush()
|
||||
session.add(
|
||||
ClientBindingRow(
|
||||
workspace_id=workspace_id,
|
||||
project_id=project_row.id,
|
||||
client_id=client_id,
|
||||
virtual_server_id=server.id,
|
||||
enabled=False,
|
||||
)
|
||||
)
|
||||
session.flush()
|
||||
record = self._record(row)
|
||||
return record, bootstrap, generate_config(record, public_host=self.public_host)
|
||||
|
||||
def list(self) -> tuple[ClientRecord, ...]:
|
||||
with self.sessions() as session:
|
||||
rows = session.scalars(
|
||||
select(ClientRow)
|
||||
.join(WorkspaceRow, WorkspaceRow.id == ClientRow.workspace_id)
|
||||
.where(WorkspaceRow.slug == "itworx")
|
||||
.order_by(ClientRow.created_at, ClientRow.id)
|
||||
).all()
|
||||
return tuple(self._record(row) for row in rows)
|
||||
|
||||
def _get(self, client_id: UUID) -> ClientRecord:
|
||||
with self.sessions() as session:
|
||||
row = session.get(ClientRow, client_id)
|
||||
if row is None:
|
||||
raise KeyError(client_id)
|
||||
return self._record(row)
|
||||
|
||||
def config(self, client_id: UUID, kind: ClientKind | None = None) -> ClientConfig:
|
||||
record = self._get(client_id)
|
||||
selected = record if kind is None else record.model_copy(update={"kind": kind})
|
||||
return generate_config(selected, public_host=self.public_host)
|
||||
|
||||
def _transition(self, client_id: UUID, status: ClientStatus) -> ClientRecord:
|
||||
now = datetime.now(UTC)
|
||||
with self.sessions() as session, session.begin():
|
||||
row = session.get(ClientRow, client_id)
|
||||
if row is None:
|
||||
raise KeyError(client_id)
|
||||
metadata = dict(row.record_metadata or {})
|
||||
metadata["operatorDisabled"] = True
|
||||
if status is ClientStatus.DISABLED:
|
||||
metadata["disabledAt"] = now.isoformat()
|
||||
row.status = "disabled"
|
||||
else:
|
||||
row.status = "revoked"
|
||||
row.revoked_at = now
|
||||
row.record_metadata = metadata
|
||||
for binding in session.scalars(
|
||||
select(ClientBindingRow).where(ClientBindingRow.client_id == client_id)
|
||||
).all():
|
||||
binding.enabled = False
|
||||
session.flush()
|
||||
return self._record(row)
|
||||
|
||||
def disable(self, client_id: UUID) -> ClientRecord:
|
||||
return self._transition(client_id, ClientStatus.DISABLED)
|
||||
|
||||
def revoke(self, client_id: UUID) -> ClientRecord:
|
||||
return self._transition(client_id, ClientStatus.REVOKED)
|
||||
|
||||
def bootstrap(self, client_id: UUID) -> BootstrapHandle:
|
||||
record = self._get(client_id)
|
||||
if record.status is ClientStatus.REVOKED:
|
||||
raise PermissionError("revoked clients cannot receive a bootstrap reference")
|
||||
handle = BootstrapHandle(
|
||||
client_id=client_id,
|
||||
reference=f"authentik-bootstrap://{uuid4()}",
|
||||
expires_at=datetime.now(UTC) + timedelta(minutes=5),
|
||||
)
|
||||
with self.sessions() as session, session.begin():
|
||||
row = session.get(ClientRow, client_id)
|
||||
if row is None:
|
||||
raise KeyError(client_id)
|
||||
metadata = dict(row.record_metadata or {})
|
||||
metadata["bootstrapReference"] = handle.reference
|
||||
metadata["bootstrapExpiresAt"] = handle.expires_at.isoformat()
|
||||
row.record_metadata = metadata
|
||||
return handle
|
||||
Reference in new issue
Block a user