2020-07-30 23:26:57 +02:00
# vim:fileencoding=utf-8:ft=python:foldmethod=marker
# statuspage/app/main.py
2020-08-11 15:02:42 +02:00
import asyncio
2020-08-07 02:00:35 +02:00
from typing import List , Optional
2020-07-30 23:26:57 +02:00
2020-08-11 11:48:46 +02:00
from fastapi import FastAPI , Depends , Security , HTTPException
from fastapi . security import OAuth2PasswordBearer , OAuth2PasswordRequestForm
2020-08-04 23:27:13 +02:00
from sqlalchemy . orm import Session
2020-08-11 11:48:46 +02:00
from app import crud , models , schemas , auth
2020-08-11 15:02:42 +02:00
from app import ultrametrics
2020-08-07 02:00:35 +02:00
from app . database import SessionLocal , engine
2020-08-04 23:27:13 +02:00
models . Base . metadata . create_all ( bind = engine )
2020-08-11 11:48:46 +02:00
oauth2_scheme = OAuth2PasswordBearer ( tokenUrl = ' /api/v1/auth/get_token ' )
2020-07-30 23:26:57 +02:00
2020-08-11 11:48:46 +02:00
app = FastAPI ( title = " Statuspage API " , description = " This documentation describes the Statuspage API. " , version = " 0.0.1 " )
2020-07-30 23:26:57 +02:00
2020-08-04 23:27:13 +02:00
def get_db ( ) :
db = SessionLocal ( )
try :
yield db
finally :
db . close ( )
2020-08-11 11:48:46 +02:00
def is_auth ( token : str = Security ( oauth2_scheme ) ) :
if not token :
raise HTTPException ( status_code = 401 , detail = { " status " : " error " , " message " : " Token not provided " } )
return auth . validate ( token )
2020-08-04 23:27:13 +02:00
2020-07-30 23:26:57 +02:00
2020-08-07 02:00:35 +02:00
def get_usr ( user_id : int , db : Session ) :
db = db
user_id = user_id
db_user = crud . get_user ( db = db , user_id = user_id )
return db_user
def get_srv ( service_id : int , db : Session ) :
db = db
service_id = service_id
db_service = crud . get_service ( db = db , service_id = service_id )
return db_service
2020-07-30 23:26:57 +02:00
@app.get ( " /api/v1/ping " )
2020-08-07 02:52:11 +02:00
async def pong ( ) :
2020-08-07 03:10:37 +02:00
""" Basic sanity check """
2020-07-30 23:26:57 +02:00
return { " ping " : " pong! " }
2020-08-04 23:27:13 +02:00
2020-08-07 02:00:35 +02:00
@app.get ( " /api/v1/service " )
2020-08-04 23:27:13 +02:00
async def read_services ( skip : int = 0 , limit : int = 100 , db : Session = Depends ( get_db ) ) :
2020-08-07 03:10:37 +02:00
""" List all services """
2020-08-04 23:27:13 +02:00
return crud . get_services ( db , skip = skip , limit = limit )
@app.post ( " /api/v1/service " , response_model = schemas . Service )
2020-08-11 11:48:46 +02:00
async def create_service ( service : schemas . ServiceCreate , db : Session = Depends ( get_db ) , token : str = Security ( is_auth ) ) :
2020-08-07 22:56:00 +02:00
""" Service types: icmp = 0, http = 1 """
if service . service_type not in [ 0 , 1 ] :
2020-08-07 22:03:42 +02:00
raise HTTPException ( status_code = 422 , detail = " Invalid service type provided " )
owner = get_usr ( service . owner_id , db )
if owner is None :
raise HTTPException ( status_code = 422 , detail = " No such owner_id " )
2020-08-04 23:27:13 +02:00
return crud . create_service ( db = db , service = service )
2020-08-07 02:00:35 +02:00
@app.get ( " /api/v1/service/ {service_id} " , response_model = schemas . Service )
2020-08-07 02:52:11 +02:00
async def read_service ( service_id : int , db : Session = Depends ( get_db ) ) :
2020-08-07 02:00:35 +02:00
db_service = get_srv ( service_id , db )
if db_service is None :
2020-08-07 22:03:42 +02:00
raise HTTPException ( status_code = 404 , detail = " Service not found " )
2020-08-07 02:00:35 +02:00
return db_service
2020-08-07 22:03:42 +02:00
@app.patch ( " /api/v1/service/ {service_id} " )
2020-08-11 11:48:46 +02:00
async def update_service ( service_id : int , service : schemas . ServiceUpdate , db : Session = Depends ( get_db ) , token : str = Security ( is_auth ) ) :
2020-08-07 02:00:35 +02:00
if ( ( service . name is None ) and ( service . owner_id is None ) and ( service . is_private is None ) and ( service . description is None ) and ( service . service_type is None ) and ( service . url is None ) and ( service . is_active is None ) ) :
raise HTTPException ( status_code = 400 , detail = " No data provided " )
db_service = get_srv ( service_id , db )
if db_service is None :
raise HTTPException ( status_code = 422 , detail = " Unprocessable entity " )
crud . update_service ( db = db , service_id = service_id , s = service )
return { " update " : " success " }
@app.delete ( " /api/v1/service/ {service_id} " )
2020-08-11 11:48:46 +02:00
async def delete_service ( service_id : int , db : Session = Depends ( get_db ) , token : str = Security ( is_auth ) ) :
2020-08-07 02:00:35 +02:00
db_service = get_srv ( service_id , db )
if db_service is None :
raise HTTPException ( status_code = 422 , detail = " Unprocessable entity " )
crud . del_service ( db = db , service_id = service_id )
return { " delete " : " success " }
2020-08-04 23:27:13 +02:00
@app.post ( " /api/v1/users " , response_model = schemas . User )
2020-08-11 11:48:46 +02:00
async def create_user ( user : schemas . UserCreate , db : Session = Depends ( get_db ) , token : str = Security ( is_auth ) ) :
2020-08-04 23:27:13 +02:00
db_user = crud . get_user_by_username ( db , name = user . name )
if db_user :
2020-08-07 22:03:42 +02:00
raise HTTPException ( status_code = 400 , detail = " Username already registered " )
2020-08-04 23:27:13 +02:00
return crud . create_user ( db = db , user = user )
2020-08-07 02:00:35 +02:00
@app.get ( " /api/v1/users " , response_model = List [ schemas . User ] )
2020-08-04 23:27:13 +02:00
async def read_users ( skip : int = 0 , limit : int = 100 , db : Session = Depends ( get_db ) ) :
2020-08-07 03:10:37 +02:00
""" List all users """
2020-08-04 23:27:13 +02:00
return crud . get_users ( db = db , skip = skip , limit = limit )
@app.get ( " /api/v1/users/ {user_id} " , response_model = schemas . User )
2020-08-07 02:52:11 +02:00
async def read_user ( user_id : int , db : Session = Depends ( get_db ) ) :
2020-08-07 02:00:35 +02:00
db_user = get_usr ( user_id , db )
2020-08-04 23:27:13 +02:00
if db_user is None :
raise HTTPException ( status_code = 404 , detail = " User not found " )
return db_user
2020-08-07 22:03:42 +02:00
@app.patch ( " /api/v1/users/ {user_id} " )
2020-08-11 11:48:46 +02:00
async def update_user ( user_id : int , user : schemas . UserUpdate , db : Session = Depends ( get_db ) , token : str = Security ( is_auth ) ) :
2020-08-11 15:02:42 +02:00
if ( ( user . name is None ) and ( user . password is None ) and ( user . full_name is None ) and ( user . is_active is None ) and ( user . is_superuser is None ) ) :
2020-08-07 02:00:35 +02:00
raise HTTPException ( status_code = 400 , detail = " No data provided " )
2020-08-07 22:03:42 +02:00
db_user = get_usr ( user_id , db )
2020-08-07 02:00:35 +02:00
if db_user is None :
raise HTTPException ( status_code = 422 , detail = " Unprocessable entity " )
crud . update_user ( db = db , user_id = user_id , user = user )
return { " update " : " success " }
2020-08-04 23:27:13 +02:00
@app.delete ( " /api/v1/users/ {user_id} " )
2020-08-11 11:48:46 +02:00
async def delete_user ( user_id : int , db : Session = Depends ( get_db ) , token : str = Security ( is_auth ) ) :
2020-08-07 22:03:42 +02:00
db_user = get_usr ( user_id , db )
2020-08-04 23:27:13 +02:00
if db_user is None :
2020-08-07 02:00:35 +02:00
raise HTTPException ( status_code = 422 , detail = " Unprocessable entity " )
2020-08-04 23:27:13 +02:00
crud . del_user ( db = db , user_id = user_id )
2020-08-07 02:00:35 +02:00
return { " delete " : " success " }
2020-08-04 23:27:13 +02:00
2020-08-11 11:48:46 +02:00
@app.post ( ' /api/v1/auth/get_token ' , response_model = schemas . Token , response_description = " Returns user access token " , summary = " Authenticate API user " , description = " Authenticate an API user and return a token for subsequent requests " )
async def get_token ( form_data : OAuth2PasswordRequestForm = Depends ( ) ) :
a = auth . login ( form_data . username , form_data . password )
if a and a [ " status " ] == " error " :
raise HTTPException ( status_code = 400 , detail = { " status " : " error " , " mesage " : " username/password incorrect " } )
return { " access_token " : a [ " token " ] , " token_type " : " bearer " }
@app.post ( ' /api/v1/auth/validate ' )
async def validate_token ( token : str ) :
a = auth . validate ( token = token )
if a :
return a
2020-08-11 15:02:42 +02:00
@app.get ( " /api/v1/metrics " , response_model = List [ schemas . Metric ] )
async def get_metrics ( skip : int = 0 , limit : int = 90 , db : Session = Depends ( get_db ) ) :
return crud . get_metrics ( db = db , skip = skip , limit = limit )
@app.get ( " /api/v1/urls " )
async def get_urls ( skip : int = 0 , limit : int = 90 , db : Session = Depends ( get_db ) ) :
return crud . get_urls ( db = db , skip = skip , limit = limit )