diff --git a/app/main.py b/app/main.py index 5b7dfbd..2e2a539 100644 --- a/app/main.py +++ b/app/main.py @@ -1,13 +1,11 @@ -from fastapi import FastAPI, Request -from fastapi.exceptions import RequestValidationError -from fastapi.responses import JSONResponse +from fastapi import FastAPI from starlette.middleware.authentication import AuthenticationMiddleware import uvicorn from app.database import engine, Base from app.models import * -from app.routers import chargepoint_v1, id_token_v1, ocpp_v1, user_v1 +from app.routers import chargepoint_v1, user_v1, ocpp_v1 from app.util.websocket_auth_backend import BasicAuthBackend Base.metadata.create_all(bind=engine) @@ -27,7 +25,6 @@ def create_app(): ) app.include_router(chargepoint_v1.router, prefix="/v1") - app.include_router(id_token_v1.router, prefix="/v1") app.include_router(user_v1.router, prefix="/v1") app.mount(path="/v1/ocpp", app=create_ocpp_app()) diff --git a/app/models/chargepoint.py b/app/models/chargepoint.py index 417431e..3c5db63 100644 --- a/app/models/chargepoint.py +++ b/app/models/chargepoint.py @@ -11,11 +11,6 @@ class ChargePoint(Base): friendly_name = Column(String, unique=True, index=True) is_active = Column(Boolean, default=True) password = Column(String) - last_seen = Column(DateTime, nullable=True) - vendor_name = Column(String, nullable=True) - model = Column(String, nullable=True) - serial_number = Column(String, nullable=True) - firmware_version = Column(String, nullable=True) connectors = relationship("Connector", cascade="delete, delete-orphan") diff --git a/app/models/id_token.py b/app/models/id_token.py index 12430bd..61651b2 100644 --- a/app/models/id_token.py +++ b/app/models/id_token.py @@ -8,7 +8,7 @@ class IdToken(Base): __tablename__ = "id_tokens" id = Column(Uuid, primary_key=True, default=uuid.uuid4) - friendly_name = Column(String) + title = Column(String) is_active = Column(Boolean, default=True) token = Column(String, index=True) diff --git a/app/ocpp_proto/chargepoint.py b/app/ocpp_proto/chargepoint.py index 7eab494..d2accb2 100644 --- a/app/ocpp_proto/chargepoint.py +++ b/app/ocpp_proto/chargepoint.py @@ -4,11 +4,10 @@ import os from ocpp.routing import on from ocpp.v201 import ChargePoint as cp from ocpp.v201 import call_result -from ocpp.v201.datatypes import IdTokenInfoType, IdTokenType -from ocpp.v201.enums import Action, RegistrationStatusType, AuthorizationStatusType, IdTokenType as IdTokenEnumType +from ocpp.v201.enums import Action, RegistrationStatusType, AuthorizationStatusType from app.database import SessionLocal -from app.models.chargepoint import ChargePoint as DbChargePoint +from app.models.chargepoint import ChargePoint from app.models.connector import Connector from app.models.id_token import IdToken from app.schemas.connector import ConnectorStatus @@ -16,13 +15,10 @@ from app.schemas.connector import ConnectorStatus class ChargePoint(cp): @on(Action.BootNotification) - async def on_boot_notification(self, charging_station, **kwargs): + async def on_boot_notification(self, charging_station, reason, **kwargs): with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.friendly_name == self.id).first() + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.friendly_name == self.id).first() db_chargepoint.last_seen = datetime.now(UTC) - for key in charging_station.keys(): - if key in db_chargepoint.__dict__: - setattr(db_chargepoint, key, charging_station[key]) db.commit() return call_result.BootNotificationPayload( current_time=datetime.now(UTC).isoformat(), @@ -33,7 +29,7 @@ class ChargePoint(cp): @on(Action.Heartbeat) async def on_heartbeat_request(self): with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.friendly_name == self.id).first() + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.friendly_name == self.id).first() db_chargepoint.last_seen = datetime.now(UTC) db.commit() return call_result.HeartbeatPayload( @@ -43,7 +39,7 @@ class ChargePoint(cp): @on(Action.StatusNotification) async def on_status_notification(self, evse_id: int, connector_id: int, connector_status: str, **kwargs): with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.friendly_name == self.id).first() + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.friendly_name == self.id).first() db_chargepoint.last_seen = datetime.now(UTC) db_connector = db.query(Connector).filter( @@ -68,38 +64,24 @@ class ChargePoint(cp): @on(Action.Authorize) async def on_authorize(self, id_token, **kwargs): - if id_token["type"] not in ["ISO14443", "ISO15693"]: - return call_result.AuthorizePayload( - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.invalid - ) - ) + if id_token == None: + return call_result.AuthorizePayload(id_token_info={'status': AuthorizationStatusType.invalid}) + if id_token.type != "ISO14443" | "ISO15693": + return call_result.AuthorizePayload(id_token_info={'status': AuthorizationStatusType.invalid}) with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.friendly_name == self.id).first() + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.friendly_name == self.id).first() db_chargepoint.last_seen = datetime.now(UTC) - db_id_token = db.query(IdToken).filter(IdToken.token == id_token["id_token"]).first() + db_id_token = db.query(IdToken).filter(IdToken.token == id_token.id).first() db.commit() - if db_id_token == None: - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.unknown - ) - else: - if db_id_token.is_active == False: - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.blocked - ) - else: - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.accepted, - group_id_token=IdTokenType( - type=IdTokenEnumType.central, - id_token=str(db_id_token.owner_id) - ) - ) - return call_result.AuthorizePayload(id_token_info) + if db_id_token == None: + return call_result.AuthorizePayload(id_token_info={'status': AuthorizationStatusType.unknown}) + if db_id_token.is_active == False: + return call_result.AuthorizePayload(id_token_info={'status': AuthorizationStatusType.blocked}) + + return call_result.AuthorizePayload(id_token_info={'status': AuthorizationStatusType.accepted, 'groupIdToken': str(db_id_token.owner_id)}) @on(Action.TransactionEvent) async def on_transaction_event(self): diff --git a/app/routers/chargepoint_v1.py b/app/routers/chargepoint_v1.py index 35d78f1..01d2b72 100644 --- a/app/routers/chargepoint_v1.py +++ b/app/routers/chargepoint_v1.py @@ -12,8 +12,8 @@ from app.models.chargepoint import ChargePoint as DbChargePoint from app.security import get_api_key router = APIRouter( - prefix="/chargepoints", - tags=["Chargepoint (v1)"], + prefix="/chargepoint", + tags=["chargepoint (v1)"], ) @router.get(path="", response_model=list[ChargePoint]) diff --git a/app/routers/id_token_v1.py b/app/routers/id_token_v1.py deleted file mode 100644 index 017aaaa..0000000 --- a/app/routers/id_token_v1.py +++ /dev/null @@ -1,96 +0,0 @@ -from uuid import UUID -from fastapi import APIRouter, HTTPException, Security -from fastapi.exceptions import RequestValidationError -from fastapi.params import Depends -from sqlalchemy.orm import Session - -from app.database import get_db -from app.schemas.id_token import IdToken, IdTokenCreate, IdTokenUpdate -from app.models.id_token import IdToken as DbIdToken -from app.models.user import User as DbUser -from app.security import get_api_key - -router = APIRouter( - prefix="/id-tokens", - tags=["IdToken (v1)"] -) - -@router.get(path="", response_model=list[IdToken]) -async def get_it_tokens( - skip: int = 0, - limit: int = 20, - api_key: str = Security(get_api_key), - db: Session = Depends(get_db) -): - return db.query(DbIdToken).offset(skip).limit(limit).all() - -@router.get(path="/{id_token_id}", response_model=IdToken) -async def get_id_token( - id_token_id: UUID, - api_key: str = Security(get_api_key), - db: Session = Depends(get_db) -): - id_token = db.get(DbIdToken, id_token_id) - if id_token == None: - raise HTTPException(status_code=404, detail="IdToken not found") - return id_token - -@router.post(path="", status_code=201, response_model=IdToken) -async def create_id_token( - create_id_token: IdTokenCreate, - api_key: str = Security(get_api_key), - db: Session = Depends(get_db) -): - owner = db.get(DbUser, create_id_token.owner_id) - if owner == None: - raise HTTPException(status_code=422, detail=[{ - "loc": ["body", "owner_id"], - "msg": "Owner not found", - "type": "invalid_relation" - }]) - id_token = DbIdToken( - friendly_name=create_id_token.friendly_name, - is_active=create_id_token.is_active, - token=create_id_token.token, - owner_id=create_id_token.owner_id - ) - db.add(id_token) - db.commit() - db.refresh(id_token) - return id_token - -@router.patch(path="/{id_token_id}", response_model=IdToken) -async def update_id_token( - id_token_id: UUID, - id_token_update: IdTokenUpdate, - api_key: str = Security(get_api_key), - db: Session = Depends(get_db) -): - id_token = db.get(DbIdToken, id_token_id) - if id_token is None: - raise HTTPException(status_code=404, detail="IdToken not found") - for key, value in id_token_update.model_dump(exclude_unset=True).items(): - if key == "owner_id": - owner = db.get(DbUser, value) - if owner == None: - raise HTTPException(status_code=422, detail=[{ - "loc": ["body", "owner_id"], - "msg": "Owner not found", - "type": "invalid_relation" - }]) - setattr(id_token, key, value) - db.commit() - return id_token - -@router.delete(path="/{id_token_id}", response_model=None) -async def delete_id_token( - id_token_id: UUID, - api_key: str = Security(get_api_key), - db: Session = Depends(get_db) -): - id_token = db.get(DbIdToken, id_token_id) - if id_token == None: - raise HTTPException(status_code=404, detail="IdToken not found") - db.delete(id_token) - db.commit() - return [] diff --git a/app/routers/user_v1.py b/app/routers/user_v1.py index 5655dad..064bc78 100644 --- a/app/routers/user_v1.py +++ b/app/routers/user_v1.py @@ -9,8 +9,8 @@ from app.models.user import User as DbUser from app.security import get_api_key router = APIRouter( - prefix="/users", - tags=["User (v1)"], + prefix="/user", + tags=["user (v1)"], ) @router.get(path="", response_model=list[User]) diff --git a/app/schemas/chargepoint.py b/app/schemas/chargepoint.py index a16db84..acb30b3 100644 --- a/app/schemas/chargepoint.py +++ b/app/schemas/chargepoint.py @@ -19,10 +19,6 @@ class ChargePointCreate(ChargePointBase): class ChargePoint(ChargePointBase): id: UUID last_seen: datetime | None - vendor_name: str | None - model: str | None - serial_number: str | None - firmware_version: str | None connectors: list[Connector] = [] class Config: diff --git a/app/schemas/id_token.py b/app/schemas/id_token.py index b8c5e06..d279913 100644 --- a/app/schemas/id_token.py +++ b/app/schemas/id_token.py @@ -1,25 +1,18 @@ -from typing import Optional from uuid import UUID from pydantic import BaseModel from app.schemas.user import User class IdTokenBase(BaseModel): - friendly_name: str + title: str is_active: bool - owner_id: UUID - token: str class IdTokenCreate(IdTokenBase): pass -class IdTokenUpdate(BaseModel): - friendly_name: Optional[str] = None - is_active: Optional[bool] = None - owner_id: Optional[UUID] = None - class IdToken(IdTokenBase): id: UUID + owner: User class Config: from_attributes = True \ No newline at end of file