diff --git a/pkgs/clan-cli/clan_cli/webui/app.py b/pkgs/clan-cli/clan_cli/webui/app.py
index de13526..8397d16 100644
--- a/pkgs/clan-cli/clan_cli/webui/app.py
+++ b/pkgs/clan-cli/clan_cli/webui/app.py
@@ -14,6 +14,7 @@ from .assets import asset_path
from .error_handlers import clan_error_handler
from .routers import health, root, socket_manager2, sql_connect # sql router hinzufügen
from .sql_db import engine
+from .tags import tags_metadata
origins = [
"http://localhost:3000",
@@ -55,6 +56,9 @@ def setup_app() -> FastAPI:
app.mount("/static", StaticFiles(directory=asset_path()), name="static")
+ # Add tag descriptions to the OpenAPI schema
+ app.openapi_tags = tags_metadata
+
for route in app.routes:
if isinstance(route, APIRoute):
route.operation_id = route.name # in this case, 'read_items'
diff --git a/pkgs/clan-cli/clan_cli/webui/routers/health.py b/pkgs/clan-cli/clan_cli/webui/routers/health.py
index b74b71b..ab0edb4 100644
--- a/pkgs/clan-cli/clan_cli/webui/routers/health.py
+++ b/pkgs/clan-cli/clan_cli/webui/routers/health.py
@@ -1,6 +1,6 @@
from fastapi import APIRouter
-from ..api_outputs import Machine, Status
+from ..schemas import Machine, Status
router = APIRouter()
diff --git a/pkgs/clan-cli/clan_cli/webui/routers/socket_manager.py b/pkgs/clan-cli/clan_cli/webui/routers/socket_manager.py
deleted file mode 100644
index cdfa46e..0000000
--- a/pkgs/clan-cli/clan_cli/webui/routers/socket_manager.py
+++ /dev/null
@@ -1,79 +0,0 @@
-from fastapi import FastAPI, WebSocket, WebSocketDisconnect
-from fastapi.responses import HTMLResponse
-from fastapi import APIRouter, Response
-
-router = APIRouter()
-
-html = """
-
-
-
- Chat
-
-
- WebSocket Chat
- Your ID:
-
-
-
-
-
-"""
-
-class ConnectionManager:
- def __init__(self) -> None:
- self.active_connections: list[WebSocket] = []
-
- async def connect(self, websocket: WebSocket) -> None:
- await websocket.accept()
- self.active_connections.append(websocket)
-
- def disconnect(self, websocket: WebSocket) -> None:
- self.active_connections.remove(websocket)
-
- async def send_personal_message(self, message: str, websocket: WebSocket) -> None:
- await websocket.send_text(message)
-
- async def broadcast(self, message: str) -> None:
- for connection in self.active_connections:
- await connection.send_text(message)
-
-
-manager = ConnectionManager()
-
-@router.get("/ws_example")
-async def get() -> HTMLResponse:
- return HTMLResponse(html)
-
-@router.websocket("/ws/{client_id}")
-async def websocket_endpoint(websocket: WebSocket, client_id: int) -> None:
- await manager.connect(websocket)
- try:
- while True:
- data = await websocket.receive_text()
- await manager.send_personal_message(f"You wrote: {data}", websocket)
- await manager.broadcast(f"Client #{client_id} says: {data}")
- except WebSocketDisconnect:
- manager.disconnect(websocket)
- await manager.broadcast(f"Client #{client_id} left the chat")
\ No newline at end of file
diff --git a/pkgs/clan-cli/clan_cli/webui/routers/sql_connect.py b/pkgs/clan-cli/clan_cli/webui/routers/sql_connect.py
index 72307de..46263e5 100644
--- a/pkgs/clan-cli/clan_cli/webui/routers/sql_connect.py
+++ b/pkgs/clan-cli/clan_cli/webui/routers/sql_connect.py
@@ -4,22 +4,39 @@ from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from .. import sql_crud, sql_db, sql_models
-from ..api_outputs import Producer, ProducerCreate
+from ..schemas import Entity, EntityCreate
+from ..tags import Tags
router = APIRouter()
-@router.get("/get_producers", response_model=List[Producer])
-def get_producers(
- skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db)
-) -> List[sql_models.Producer]:
- producers = sql_crud.get_producers(db, skip=skip, limit=limit)
- return producers
+# @router.get("/api/v1/get_producers", response_model=List[Producer], tags=[Tags.producers])
+# def get_producers(
+# skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db)
+# ) -> List[sql_models.Producer]:
+# producers = sql_crud.get_producers(db, skip=skip, limit=limit)
+# return producers
-@router.post("/create_producers", response_model=Producer)
-def create_producers(
- producer: ProducerCreate, db: Session = Depends(sql_db.get_db)
-) -> Producer:
+# @router.post("/api/v1/create_producer", response_model=Producer, tags=[Tags.producers])
+# def create_producer(
+# producer: ProducerCreate, db: Session = Depends(sql_db.get_db)
+# ) -> Producer:
+# # todo checken ob schon da ...
+# return sql_crud.create_producer(db=db, producer=producer)
+
+
+@router.post("/api/v1/create_entity", response_model=Entity, tags=[Tags.entities])
+def create_entity(
+ entity: EntityCreate, db: Session = Depends(sql_db.get_db)
+) -> EntityCreate:
# todo checken ob schon da ...
- return sql_crud.create_producer(db=db, producer=producer)
+ return sql_crud.create_entity(db, entity)
+
+
+@router.get("/api/v1/get_entities", response_model=List[Entity], tags=[Tags.entities])
+def get_entities(
+ skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db)
+) -> List[sql_models.Entity]:
+ entities = sql_crud.get_entities(db, skip=skip, limit=limit)
+ return entities
diff --git a/pkgs/clan-cli/clan_cli/webui/api_outputs.py b/pkgs/clan-cli/clan_cli/webui/schemas.py
similarity index 74%
rename from pkgs/clan-cli/clan_cli/webui/api_outputs.py
rename to pkgs/clan-cli/clan_cli/webui/schemas.py
index f0f2632..cb118f2 100644
--- a/pkgs/clan-cli/clan_cli/webui/api_outputs.py
+++ b/pkgs/clan-cli/clan_cli/webui/schemas.py
@@ -14,6 +14,23 @@ class Machine(BaseModel):
status: Status
+class EntityBase(BaseModel):
+ did: str = "did:sov:test:1234"
+ name: str = "C1"
+ ip: str = "127.0.0.1"
+ attached: bool = False
+ other: dict = {"test": "test"}
+
+
+class Entity(EntityBase):
+ class Config:
+ orm_mode = True
+
+
+class EntityCreate(EntityBase):
+ pass
+
+
class RepositoryBase(BaseModel):
title: str
description: str | None = None
diff --git a/pkgs/clan-cli/clan_cli/webui/sql_crud.py b/pkgs/clan-cli/clan_cli/webui/sql_crud.py
index 0c66d52..c3d5a61 100644
--- a/pkgs/clan-cli/clan_cli/webui/sql_crud.py
+++ b/pkgs/clan-cli/clan_cli/webui/sql_crud.py
@@ -2,37 +2,51 @@ from typing import List
from sqlalchemy.orm import Session
-from . import api_outputs, sql_models
+from . import schemas, sql_models
-def get_producers(
- db: Session, skip: int = 0, limit: int = 100
-) -> List[sql_models.Producer]:
- return db.query(sql_models.Producer).offset(skip).limit(limit).all()
-
-
-def create_producer(
- db: Session, producer: api_outputs.ProducerCreate
-) -> sql_models.Producer:
- jsonblob_init = {"test_repo": "jsonblob_create"}
- db_producer = sql_models.Producer(jsonblob=jsonblob_init)
- db.add(db_producer)
+def create_entity(db: Session, entity: schemas.EntityCreate) -> sql_models.Entity:
+ db_entity = sql_models.Entity(**entity.dict())
+ db.add(db_entity)
db.commit()
- db.refresh(db_producer)
- return db_producer
+ db.refresh(db_entity)
+ return db_entity
-def get_repositories(
+def get_entities(
db: Session, skip: int = 0, limit: int = 100
-) -> List[sql_models.Repository]:
- return db.query(sql_models.Repository).offset(skip).limit(limit).all()
+) -> List[sql_models.Entity]:
+ return db.query(sql_models.Entity).offset(skip).limit(limit).all()
-def create_repository(
- db: Session, repository: api_outputs.RepositoryCreate, producers_id: int
-) -> sql_models.Repository:
- db_repository = sql_models.Repository(**repository.dict(), prod_id=producers_id)
- db.add(db_repository)
- db.commit()
- db.refresh(db_repository)
- return db_repository
+# def get_producers(
+# db: Session, skip: int = 0, limit: int = 100
+# ) -> List[sql_models.Producer]:
+# return db.query(sql_models.Producer).offset(skip).limit(limit).all()
+
+
+# def create_producer(
+# db: Session, producer: schemas.ProducerCreate
+# ) -> sql_models.Producer:
+# jsonblob_init = {"test_repo": "jsonblob_create"}
+# db_producer = sql_models.Producer(jsonblob=jsonblob_init)
+# db.add(db_producer)
+# db.commit()
+# db.refresh(db_producer)
+# return db_producer
+
+
+# def get_repositories(
+# db: Session, skip: int = 0, limit: int = 100
+# ) -> List[sql_models.Repository]:
+# return db.query(sql_models.Repository).offset(skip).limit(limit).all()
+
+
+# def create_repository(
+# db: Session, repository: schemas.RepositoryCreate, producers_id: int
+# ) -> sql_models.Repository:
+# db_repository = sql_models.Repository(**repository.dict(), prod_id=producers_id)
+# db.add(db_repository)
+# db.commit()
+# db.refresh(db_repository)
+# return db_repository
diff --git a/pkgs/clan-cli/clan_cli/webui/sql_models.py b/pkgs/clan-cli/clan_cli/webui/sql_models.py
index f357238..d9cf59f 100644
--- a/pkgs/clan-cli/clan_cli/webui/sql_models.py
+++ b/pkgs/clan-cli/clan_cli/webui/sql_models.py
@@ -1,23 +1,90 @@
-from sqlalchemy import JSON, Column, ForeignKey, Integer
+from sqlalchemy import JSON, Boolean, Column, DateTime, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .sql_db import Base
+# Relationsship example
+# https://dev.to/freddiemazzilli/flask-sqlalchemy-relationships-exploring-relationship-associations-igo
-class Producer(Base):
+
+class Entity(Base):
+ __tablename__ = "entities"
+
+ ## Queryable body ##
+ did = Column(String, primary_key=True, index=True)
+ name = Column(String, index=True)
+ ip = Column(String, index=True)
+ attached = Column(Boolean, index=True)
+
+ ## Non queryable body ##
+ # In here we deposit: Network, Roles, Visible, etc.
+ other = Column(JSON)
+
+ ## Relations ##
+ producers = relationship("Producer", back_populates="entity")
+ consumers = relationship("Consumer", back_populates="entity")
+ # repository = relationship("Repository", uselist=False, back_populates="entity")
+
+
+class ProducerAbstract(Base):
+ __abstract__ = True
+
+ # Queryable body
+ id = Column(Integer, primary_key=True, index=True)
+ service_name = Column(String, unique=True, index=True)
+ service_type = Column(String, index=True)
+ endpoint_url = Column(String, index=True)
+ status = Column(String, index=True)
+
+ ## Non queryable body ##
+ # In here we deposit: Action
+ other = Column(JSON)
+
+
+class Producer(ProducerAbstract):
__tablename__ = "producers"
+ # Usage is the consumers column
+
+ ## Relations ##
+ # One entity can have many producers
+ entity = relationship("Entity", back_populates="producers")
+ entity_did = Column(Integer, ForeignKey("entities.did"))
+
+ # One producer has many consumers
+ consumers = relationship("Consumer", back_populates="producer")
+
+
+class Consumer(Base):
+ __tablename__ = "consumers"
+
+ ## Queryable body ##
id = Column(Integer, primary_key=True, index=True)
- jsonblob = Column(JSON)
- repos = relationship("Repository", back_populates="producer")
+ ## Relations ##
+ # one entity can have many consumers
+ entity = relationship("Entity", back_populates="consumers")
+ entity_did = Column(Integer, ForeignKey("entities.did"))
+
+ # one consumer has one producer
+ producer = relationship("Producer", back_populates="consumers")
+ producer_id = Column(Integer, ForeignKey("producers.id"))
-class Repository(Base):
- __tablename__ = "repositories"
+# class Repository(ProducerAbstract):
+# __tablename__ = "repositories"
- id = Column(Integer, primary_key=True, index=True)
- jsonblob = Column(JSON)
- prod_id = Column(Integer, ForeignKey("producers.id"))
+# # one repository has one entity
+# entity = relationship("Entity", back_populates="repository")
+# entity_did = Column(Integer, ForeignKey("entities.did"))
- producer = relationship("Producer", back_populates="repos")
+
+# TODO: Ask how this works exactly
+class Resolution(Base):
+ __tablename__ = "resolutions"
+
+ id = Column(Integer, primary_key=True)
+ requester_name = Column(String, index=True)
+ requester_did = Column(String, index=True)
+ resolved_did = Column(String, index=True)
+ timestamp = Column(DateTime, index=True)
diff --git a/pkgs/clan-cli/clan_cli/webui/tags.py b/pkgs/clan-cli/clan_cli/webui/tags.py
new file mode 100644
index 0000000..78f7968
--- /dev/null
+++ b/pkgs/clan-cli/clan_cli/webui/tags.py
@@ -0,0 +1,32 @@
+from enum import Enum
+from typing import Any, Dict, List
+
+
+class Tags(Enum):
+ producers = "producers"
+ consumers = "consumers"
+ entities = "entities"
+ repositories = "repositories"
+
+ def __str__(self) -> str:
+ return self.value
+
+
+tags_metadata: List[Dict[str, Any]] = [
+ {
+ "name": str(Tags.producers),
+ "description": "Operations on a producer.",
+ },
+ {
+ "name": str(Tags.consumers),
+ "description": "Operations on a consumer.",
+ },
+ {
+ "name": str(Tags.entities),
+ "description": "Operations on an entity.",
+ },
+ {
+ "name": str(Tags.repositories),
+ "description": "Operations on a repository.",
+ },
+]