1from typing import List
2
3import sqlalchemy
4from fastapi import APIRouter, Depends
5from fastapi import HTTPException
6
7from app import marznode
8from app.db import crud
9from app.dependencies import DBDep, sudo_admin
10from app.models.service import (ServiceCreate, ServiceModify,
11 ServiceResponse)
12
13router = APIRouter(prefix="/services", dependencies=[Depends(sudo_admin)], tags=['Service'])
14
15
16@router.post("", response_model=ServiceResponse)
17def add_service(new_service: ServiceCreate,
18 db: DBDep):
19 """
20 Add a new service
21
22 - **name** service name
23 - **inbounds** list of inbound ids
24 """
25 try:
26 return crud.create_service(db, new_service)
27 except sqlalchemy.exc.IntegrityError:
28 db.rollback()
29 raise HTTPException(status_code=409, detail="Service by this name already exists")
30
31
32@router.get("/{id}", response_model=ServiceResponse)
33def get_service(id: int, db: DBDep):
34 """
35 Get Service information with id
36 """
37 dbservice = crud.get_service(db, id)
38 if not dbservice:
39 raise HTTPException(status_code=404, detail="Service not found")
40
41 return dbservice
42
43
44@router.put("/{id}", response_model=ServiceResponse)
45async def modify_service(id: int,
46 modification: ServiceModify,
47 db: DBDep):
48 """
49 Modify Service
50
51 - **name** can be up to 64 characters
52 - **inbounds** list of inbound ids. if not specified no change will be applied;
53 in case of an empty list all inbounds would be removed.
54 """
55 # TODO: Update all affected users in nodes
56 dbservice = crud.get_service(db, id)
57 if not dbservice:
58 raise HTTPException(status_code=404, detail="Service not found")
59 old_inbounds = {(i.node_id, i.protocol, i.tag) for i in dbservice.inbounds}
60 try:
61 response = crud.update_service(db, dbservice, modification)
62 except sqlalchemy.exc.IntegrityError:
63 db.rollback()
64 raise HTTPException(status_code=409, detail="problem updating the service")
65 else:
66 for user in response.users:
67 await marznode.operations.update_user(user, old_inbounds=old_inbounds)
68 return response
69
70
71@router.delete("/{id}")
72def remove_service(id: int,
73 db: DBDep):
74 dbservice = crud.get_service(db, id)
75 if not dbservice:
76 raise HTTPException(status_code=404, detail="Service not found")
77
78 crud.remove_service(db, dbservice)
79 return dict()
80
81
82@router.get("", response_model=List[ServiceResponse])
83def get_services(db: DBDep,
84 offset: int = None,
85 limit: int = None):
86 return crud.get_services(db) # , offset, limit)