gitscope
← marzneshin / v0.3.1 / app/routes/service.py
https://dev.kronoz.win/r/marzneshin.git
app/routes/service.py · Python
Blame Raw
  1import sqlalchemy
  2from fastapi import APIRouter, Query
  3from fastapi import HTTPException
  4from fastapi_pagination.ext.sqlalchemy import paginate
  5from fastapi_pagination.links import Page
  6
  7from app import marznode
  8from app.db import crud
  9from app.db.models import Service, User
 10from app.dependencies import DBDep, AdminDep, SudoAdminDep
 11from app.models.proxy import Inbound
 12from app.models.service import ServiceCreate, ServiceModify, ServiceResponse
 13from app.models.user import UserResponse
 14
 15router = APIRouter(prefix="/services", tags=["Service"])
 16
 17
 18@router.get("", response_model=Page[ServiceResponse])
 19def get_services(db: DBDep, admin: AdminDep, name: str = Query(None)):
 20    query = db.query(Service)
 21    if name:
 22        query = query.filter(Service.name.ilike(f"%{name}%"))
 23    return paginate(query)
 24
 25
 26@router.post("", response_model=ServiceResponse)
 27def add_service(new_service: ServiceCreate, db: DBDep, admin: SudoAdminDep):
 28    """
 29    Add a new service
 30
 31    - **name** service name
 32    - **inbounds** list of inbound ids
 33    """
 34    try:
 35        return crud.create_service(db, new_service)
 36    except sqlalchemy.exc.IntegrityError:
 37        db.rollback()
 38        raise HTTPException(
 39            status_code=409, detail="Service by this name already exists"
 40        )
 41
 42
 43@router.get("/{id}", response_model=ServiceResponse)
 44def get_service(id: int, db: DBDep, admin: AdminDep):
 45    """
 46    Get Service information with id
 47    """
 48    dbservice = crud.get_service(db, id)
 49    if not dbservice:
 50        raise HTTPException(status_code=404, detail="Service not found")
 51
 52    return dbservice
 53
 54
 55@router.get("/{id}/users", response_model=Page[UserResponse])
 56def get_service_users(id: int, db: DBDep, admin: SudoAdminDep):
 57    """
 58    Get service users
 59    """
 60    service = crud.get_service(db, id)
 61
 62    if not service:
 63        raise HTTPException(status_code=404, detail="Service not found")
 64
 65    query = db.query(User).join(User.services).where(Service.id == service.id)
 66
 67    return paginate(query)
 68
 69
 70@router.get("/{id}/inbounds", response_model=Page[Inbound])
 71def get_service_inbounds(id: int, db: DBDep, admin: SudoAdminDep):
 72    """
 73    Get service inbounds
 74    """
 75    service = crud.get_service(db, id)
 76
 77    if not service:
 78        raise HTTPException(status_code=404, detail="Service not found")
 79
 80    query = (
 81        db.query(Inbound)
 82        .join(Inbound.services)
 83        .where(Service.id == service.id)
 84    )
 85
 86    return paginate(query)
 87
 88
 89@router.put("/{id}", response_model=ServiceResponse)
 90async def modify_service(
 91    id: int, modification: ServiceModify, db: DBDep, admin: SudoAdminDep
 92):
 93    """
 94    Modify Service
 95
 96    - **name** can be up to 64 characters
 97    - **inbounds** list of inbound ids. if not specified no change will be applied;
 98    in case of an empty list all inbounds would be removed.
 99    """
100    dbservice = crud.get_service(db, id)
101    if not dbservice:
102        raise HTTPException(status_code=404, detail="Service not found")
103    old_inbounds = {(i.node_id, i.protocol, i.tag) for i in dbservice.inbounds}
104    try:
105        response = crud.update_service(db, dbservice, modification)
106    except sqlalchemy.exc.IntegrityError:
107        db.rollback()
108        raise HTTPException(
109            status_code=409, detail="problem updating the service"
110        )
111    else:
112        for user in response.users:
113            if user.activated:
114                marznode.operations.update_user(
115                    user, old_inbounds=old_inbounds
116                )
117        return response
118
119
120@router.delete("/{id}")
121def remove_service(id: int, db: DBDep, admin: SudoAdminDep):
122    dbservice = crud.get_service(db, id)
123    if not dbservice:
124        raise HTTPException(status_code=404, detail="Service not found")
125
126    crud.remove_service(db, dbservice)
127    return dict()