gitscope
← marzneshin / v0.3.0 / app/routes/service.py
https://dev.kronoz.win/r/marzneshin.git
app/routes/service.py · Python
Blame Raw
 1import sqlalchemy
 2from fastapi import APIRouter, Depends, 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
10from app.dependencies import DBDep, sudo_admin
11from app.models.service import ServiceCreate, ServiceModify, ServiceResponse
12
13router = APIRouter(
14    prefix="/services", dependencies=[Depends(sudo_admin)], tags=["Service"]
15)
16
17
18@router.get("", response_model=Page[ServiceResponse])
19def get_services(db: DBDep, 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):
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):
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.put("/{id}", response_model=ServiceResponse)
56async def modify_service(id: int, modification: ServiceModify, db: DBDep):
57    """
58    Modify Service
59
60    - **name** can be up to 64 characters
61    - **inbounds** list of inbound ids. if not specified no change will be applied;
62    in case of an empty list all inbounds would be removed.
63    """
64    dbservice = crud.get_service(db, id)
65    if not dbservice:
66        raise HTTPException(status_code=404, detail="Service not found")
67    old_inbounds = {(i.node_id, i.protocol, i.tag) for i in dbservice.inbounds}
68    try:
69        response = crud.update_service(db, dbservice, modification)
70    except sqlalchemy.exc.IntegrityError:
71        db.rollback()
72        raise HTTPException(status_code=409, detail="problem updating the service")
73    else:
74        for user in response.users:
75            await marznode.operations.update_user(user, old_inbounds=old_inbounds)
76        return response
77
78
79@router.delete("/{id}")
80def remove_service(id: int, db: DBDep):
81    dbservice = crud.get_service(db, id)
82    if not dbservice:
83        raise HTTPException(status_code=404, detail="Service not found")
84
85    crud.remove_service(db, dbservice)
86    return dict()