From e33d74308a412ca4ccdd77d9a23fff72209b33c6 Mon Sep 17 00:00:00 2001 From: BluemediaGER Date: Sun, 14 Apr 2024 01:42:51 +0200 Subject: [PATCH] Add user router --- README.md | 2 +- app/main.py | 3 +- app/routers/chargepoint_v1.py | 16 ++++---- app/routers/user_v1.py | 77 +++++++++++++++++++++++++++++++++++ app/schemas/user.py | 8 ++-- 5 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 app/routers/user_v1.py diff --git a/README.md b/README.md index 5db7e3e..e8dbadc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Simple OCCP Central System -This is a simple implementation of a basic OCPP 2.0.1 compliant central system (backend) for EV charging stations. +This is a simple implementation of a basic [OCPP](https://openchargealliance.org/protocols/open-charge-point-protocol/) 2.0.1 compliant central system (backend) for EV charging stations. ## Features diff --git a/app/main.py b/app/main.py index b9cbb02..2e2a539 100644 --- a/app/main.py +++ b/app/main.py @@ -5,7 +5,7 @@ import uvicorn from app.database import engine, Base from app.models import * -from app.routers import chargepoint_v1, ocpp_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) @@ -25,6 +25,7 @@ def create_app(): ) app.include_router(chargepoint_v1.router, prefix="/v1") + app.include_router(user_v1.router, prefix="/v1") app.mount(path="/v1/ocpp", app=create_ocpp_app()) return app diff --git a/app/routers/chargepoint_v1.py b/app/routers/chargepoint_v1.py index 806bdc3..01d2b72 100644 --- a/app/routers/chargepoint_v1.py +++ b/app/routers/chargepoint_v1.py @@ -8,7 +8,7 @@ from sqlalchemy.orm import Session from app.database import get_db from app.ocpp_proto import chargepoint_manager from app.schemas.chargepoint import ChargePoint, ChargePointCreate, ChargePointUpdate, ChargePointPassword, ChargePointConnectionInfo -from app.models.chargepoint import ChargePoint as DBChargePoint +from app.models.chargepoint import ChargePoint as DbChargePoint from app.security import get_api_key router = APIRouter( @@ -23,7 +23,7 @@ async def get_chargepoints( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - return db.query(DBChargePoint).offset(skip).limit(limit).all() + return db.query(DbChargePoint).offset(skip).limit(limit).all() @router.get(path="/{chargepoint_id}", response_model=ChargePoint) async def get_chargepoint( @@ -31,7 +31,7 @@ async def get_chargepoint( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - chargepoint = db.query(DBChargePoint).filter(DBChargePoint.id == chargepoint_id).first() + chargepoint = db.get(DbChargePoint, chargepoint_id) if chargepoint is None: raise HTTPException(status_code=404, detail="Chargepoint not found") return chargepoint @@ -42,7 +42,7 @@ async def get_chargepoint_password( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - chargepoint = db.query(DBChargePoint).filter(DBChargePoint.id == chargepoint_id).first() + chargepoint = db.get(DbChargePoint, chargepoint_id) if chargepoint is None: raise HTTPException(status_code=404, detail="Chargepoint not found") return ChargePointPassword(password=chargepoint.password) @@ -53,7 +53,7 @@ async def reset_chargepoint_password( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - chargepoint = db.query(DBChargePoint).filter(DBChargePoint.id == chargepoint_id).first() + chargepoint = db.get(DbChargePoint, chargepoint_id) if chargepoint is None: raise HTTPException(status_code=404, detail="Chargepoint not found") chargepoint.password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(24)) @@ -66,7 +66,7 @@ async def create_chargepoint( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - chargepoint_db = DBChargePoint( + chargepoint_db = DbChargePoint( friendly_name=chargepoint.friendly_name, is_active=chargepoint.is_active, password=''.join(random.choice(string.ascii_letters + string.digits) for i in range(24)) @@ -83,7 +83,7 @@ async def update_chargepoint( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - chargepoint = db.query(DBChargePoint).filter(DBChargePoint.id == chargepoint_id).first() + chargepoint = db.get(DbChargePoint, chargepoint_id) if chargepoint is None: raise HTTPException(status_code=404, detail="Chargepoint not found") for key, value in chargepoint_update.model_dump(exclude_unset=True).items(): @@ -97,7 +97,7 @@ async def delete_chargepoint( api_key: str = Security(get_api_key), db: Session = Depends(get_db) ): - chargepoint = db.query(DBChargePoint).filter(DBChargePoint.id == chargepoint_id).first() + chargepoint = db.get(DbChargePoint, chargepoint_id) if chargepoint is None: raise HTTPException(status_code=404, detail="Chargepoint not found") db.delete(chargepoint) diff --git a/app/routers/user_v1.py b/app/routers/user_v1.py new file mode 100644 index 0000000..064bc78 --- /dev/null +++ b/app/routers/user_v1.py @@ -0,0 +1,77 @@ +from uuid import UUID +from fastapi import APIRouter, HTTPException, Security +from fastapi.params import Depends +from sqlalchemy.orm import Session + +from app.database import get_db +from app.schemas.user import User, UserCreate, UserUpdate +from app.models.user import User as DbUser +from app.security import get_api_key + +router = APIRouter( + prefix="/user", + tags=["user (v1)"], +) + +@router.get(path="", response_model=list[User]) +async def get_users( + skip: int = 0, + limit: int = 20, + api_key: str = Security(get_api_key), + db: Session = Depends(get_db) +): + return db.query(DbUser).offset(skip).limit(limit).all() + +@router.get(path="/{user_id}", response_model=User) +async def get_user( + user_id: UUID, + api_key: str = Security(get_api_key), + db: Session = Depends(get_db) +): + user = db.get(DbUser, user_id) + if user == None: + raise HTTPException(status_code=404, detail="User not found") + return user + +@router.post(path="", status_code=201, response_model=User) +async def create_user( + create_user: UserCreate, + api_key: str = Security(get_api_key), + db: Session = Depends(get_db) +): + db_user = DbUser( + friendly_name=create_user.friendly_name, + is_active=create_user.is_active + ) + db.add(db_user) + db.commit() + db.refresh(db_user) + return db_user + +@router.patch(path="/{user_id}", response_model=User) +async def update_user( + user_id: UUID, + user_update: UserUpdate, + api_key: str = Security(get_api_key), + db: Session = Depends(get_db) +): + user = db.get(DbUser, user_id) + if user is None: + raise HTTPException(status_code=404, detail="User not found") + for key, value in user_update.model_dump(exclude_unset=True).items(): + setattr(user, key, value) + db.commit() + return user + +@router.delete(path="/{user_id}", response_model=None) +async def delete_user( + user_id: UUID, + api_key: str = Security(get_api_key), + db: Session = Depends(get_db) +): + user = db.get(DbUser, user_id) + if user == None: + raise HTTPException(status_code=404, detail="User not found") + db.delete(user) + db.commit() + return [] diff --git a/app/schemas/user.py b/app/schemas/user.py index c06817b..d9c3349 100644 --- a/app/schemas/user.py +++ b/app/schemas/user.py @@ -1,18 +1,20 @@ +from typing import Optional from uuid import UUID from pydantic import BaseModel -from app.schemas.id_token import IdToken - class UserBase(BaseModel): friendly_name: str is_active: bool +class UserUpdate(BaseModel): + friendly_name: Optional[str] = None + is_active: Optional[bool] = None + class UserCreate(UserBase): pass class User(UserBase): id: UUID - id_tokens: list[IdToken] = [] class Config: from_attributes = True \ No newline at end of file