From 2dd2258472d1dbb91bdb8353da1a92ca4434ba96 Mon Sep 17 00:00:00 2001 From: surtur Date: Tue, 4 Aug 2020 23:27:13 +0200 Subject: [PATCH] feat: {user,service} {creation,deletion,listing} * also updated requirements.txt accordingly --- app/crud.py | 46 ++++++++++++++++++++++++++++++++++++++ app/database.py | 12 ++++++++++ app/main.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++- app/models.py | 35 +++++++++++++++++++++++++++++ app/schemas.py | 52 +++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 +++ 6 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 app/crud.py create mode 100644 app/database.py create mode 100644 app/models.py create mode 100644 app/schemas.py diff --git a/app/crud.py b/app/crud.py new file mode 100644 index 0000000..b40f41a --- /dev/null +++ b/app/crud.py @@ -0,0 +1,46 @@ +import bcrypt, time +from sqlalchemy.orm import Session +from . import models, schemas + + +def get_user(db: Session, user_id: int): + return db.query(models.User).filter(models.User.id == user_id).first() + +def del_user(db: Session, user_id: int): + db.query(models.User).filter(models.User.id == user_id).delete() + db.commit() + return + +def get_user_by_username(db: Session, name: str): + return db.query(models.User).filter(models.User.name == name).first() + + +def get_users(db: Session, skip: int = 0, limit: int = 100): + return db.query(models.User).offset(skip).limit(limit).all() + + +def create_user(db: Session, user: schemas.UserCreate): + h_et_s = bcrypt.hashpw(user.password.encode(), bcrypt.gensalt()) + db_user = models.User(**user.dict()) + db_user.name=user.name + db_user.password=h_et_s + db_user.created_unix = time.time() + db.add(db_user) + db.commit() + db.refresh(db_user) + return db_user + + +def get_services(db: Session, skip: int = 0, limit: int = 100): + return db.query(models.Service).offset(skip).limit(limit).all() + +def create_service(db: Session, service: schemas.ServiceCreate): + db_item = models.Service(**service.dict()) + """ inject updated+created times here """ + db_item.updated_unix = time.time() + db_item.created_unix = time.time() + db.add(db_item) + db.commit() + db.refresh(db_item) + return db_item + diff --git a/app/database.py b/app/database.py new file mode 100644 index 0000000..e32fc2c --- /dev/null +++ b/app/database.py @@ -0,0 +1,12 @@ +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db" + +engine = create_engine( + SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} +) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() diff --git a/app/main.py b/app/main.py index ea8e2d8..f4c7863 100644 --- a/app/main.py +++ b/app/main.py @@ -1,12 +1,67 @@ # vim:fileencoding=utf-8:ft=python:foldmethod=marker # statuspage/app/main.py -from fastapi import FastAPI +from typing import List +from fastapi import FastAPI, Depends, HTTPException +from pydantic import BaseModel +from sqlalchemy.orm import Session + +from . import crud, models, schemas +from .database import SessionLocal, engine + + +models.Base.metadata.create_all(bind=engine) app = FastAPI() +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + + @app.get("/api/v1/ping") def pong(): return {"ping": "pong!"} + +@app.get("/api/v1/service/") +async def read_services(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + return crud.get_services(db, skip=skip, limit=limit) + +@app.post("/api/v1/service", response_model=schemas.Service) +async def create_service(service: schemas.ServiceCreate, db: Session = Depends(get_db)): + return crud.create_service(db=db, service=service) + + +@app.post("/api/v1/users", response_model=schemas.User) +async def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): + db_user = crud.get_user_by_username(db, name=user.name) + if db_user: + raise HTTPException(status_code=400, detail="username already registered") + return crud.create_user(db=db, user=user) + +# @app.get("/api/v1/users", response_model=List[schemas.User]) +@app.get("/api/v1/users") +async def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + return crud.get_users(db=db, skip=skip, limit=limit) + +@app.get("/api/v1/users/{user_id}", response_model=schemas.User) +def read_user(user_id: int, db: Session = Depends(get_db)): + db_user = crud.get_user(db=db, user_id=user_id) + if db_user is None: + raise HTTPException(status_code=404, detail="User not found") + return db_user + +@app.delete("/api/v1/users/{user_id}") +async def read_user(user_id: int, db: Session = Depends(get_db)): + db_user = crud.get_user(db=db, user_id=user_id) + if db_user is None: + raise HTTPException(status_code=404, detail="User not found") + crud.del_user(db=db, user_id=user_id) + return {"deletion":"successful"} + diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..367ca4b --- /dev/null +++ b/app/models.py @@ -0,0 +1,35 @@ +from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Float +from sqlalchemy.orm import relationship + +from .database import Base + +class Service(Base): + __tablename__ = "service" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True) + is_private = Column(Boolean, default=True) + description = Column(String) + service_type = Column(Integer) + url = Column(String) + owner_id = Column(Integer, ForeignKey("user.id"), index=True) + is_active = Column(Boolean, default=True, index=True) + created_unix = Column(Float) + updated_unix = Column(Float) + + user = relationship("User", back_populates="service") + + +class User(Base): + __tablename__ = "user" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, unique=True, index=True) + full_name = Column(String, index=True) + password = Column(String) + is_active = Column(Boolean, default=True, index=True) + created_unix = Column(Float) + last_login_unix = Column(Float) + + service = relationship("Service", back_populates="user") + diff --git a/app/schemas.py b/app/schemas.py new file mode 100644 index 0000000..f9dbcff --- /dev/null +++ b/app/schemas.py @@ -0,0 +1,52 @@ +import time +from typing import List, Optional +from pydantic import BaseModel + + +class ServiceBase(BaseModel): + name: str + is_private: bool = True + description: Optional[str] = None + service_type: int + url: str + owner_id: Optional[int] = None + is_active: bool = True + updated_unix: float + +class Service(BaseModel): + name: str + owner_id: int + is_active: bool = True + created_unix: float + +class ServiceCreate(ServiceBase): + pass + +class Service(ServiceBase): + owner_id: int + + class Config: + orm_mode = True + + +class UserBase(BaseModel): + name: str + full_name: Optional[str] = None + is_active: bool = True + +class User(BaseModel): + name: str + full_name: Optional[str] = None + is_active: bool = True + last_login_unix: float + created_unix: float + +class UserCreate(UserBase): + password: str + +class User(UserBase): + pass + + class Config: + orm_mode = True + diff --git a/requirements.txt b/requirements.txt index 97dc7cd..434328f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,5 @@ fastapi uvicorn +pydantic +sqlalchemy +bcrypt