gitscope
← marzneshin / Diff · d6e2aad → d6e2aad
Changes d6e2aad..d6e2aad
Patch commit
diff --git a/app/marznode/operations.py b/app/marznode/operations.py
index 667e66b..0a7fef9 100644
--- a/app/marznode/operations.py
+++ b/app/marznode/operations.py
@@ -29,7 +29,16 @@ async def update_user(user: "DBUser", old_inbounds: set | None = None):
node_inbounds[inb[0]]
for node_id, tags in node_inbounds.items():
- await marznode.nodes[node_id].update_user(user=user, inbounds=tags)
+ if marznode.nodes.get(node_id):
+ await marznode.nodes[node_id].update_user(user=user, inbounds=tags)
+
+
+async def remove_user(user: "DBUser"):
+ node_ids = set(inb.id for inb in user.inbounds)
+
+ for node_id in node_ids:
+ if marznode.nodes.get(node_id):
+ await marznode.nodes[node_id].update_user(user=user, inbounds=[])
async def remove_node(node_id: int):
diff --git a/app/models/admin.py b/app/models/admin.py
index 41e9982..9c99b0b 100644
--- a/app/models/admin.py
+++ b/app/models/admin.py
@@ -5,7 +5,7 @@ from passlib.context import CryptContext
from pydantic import ConfigDict, BaseModel
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/admin/token") # Admin view url
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/admins/token") # Admin view url
class Token(BaseModel):
diff --git a/app/models/user.py b/app/models/user.py
index 9e49c0b..fec35a5 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -67,7 +67,6 @@ class UserBase(BaseModel):
on_hold_expire_duration: Optional[int] = Field(None, nullable=True)
on_hold_timeout: Optional[Union[datetime, None]] = Field(None, nullable=True)
-
@field_validator("username")
@classmethod
def validate_username(cls, v: str):
diff --git a/app/routes/service.py b/app/routes/service.py
index bae709f..b3dd628 100644
--- a/app/routes/service.py
+++ b/app/routes/service.py
@@ -4,6 +4,7 @@ import sqlalchemy
from fastapi import APIRouter, Depends
from fastapi import HTTPException
+from app import marznode
from app.db import crud
from app.dependencies import DBDep, sudo_admin
from app.models.service import (ServiceCreate, ServiceModify,
@@ -16,12 +17,10 @@ router = APIRouter(prefix="/services", dependencies=[Depends(sudo_admin)], tags=
def add_service(new_service: ServiceCreate,
db: DBDep):
"""
- Add a new user template
+ Add a new service
- - **name** can be up to 64 characters
- - **data_limit** must be in bytes and larger or equal to 0
- - **expire_duration** must be in seconds and larger or equal to 0
- - **inbounds** dictionary of protocol:inbound_tags, empty means all inbounds
+ - **name** service name
+ - **inbounds** list of inbound ids
"""
try:
return crud.create_service(db, new_service)
@@ -43,15 +42,13 @@ def get_service(id: int, db: DBDep):
@router.put("/{id}", response_model=ServiceResponse)
-def modify_service(id: int,
+async def modify_service(id: int,
modification: ServiceModify,
db: DBDep):
"""
Modify Service
- **name** can be up to 64 characters
- - **data_limit** must be in bytes and larger or equal to 0
- - **expire_duration** must be in seconds and larger or equat to 0
- **inbounds** list of inbound ids. if not specified no change will be applied;
in case of an empty list all inbounds would be removed.
"""
@@ -59,12 +56,16 @@ def modify_service(id: int,
dbservice = crud.get_service(db, id)
if not dbservice:
raise HTTPException(status_code=404, detail="Service not found")
-
+ old_inbounds = {(i.node_id, i.protocol, i.tag) for i in dbservice.inbounds}
try:
- return crud.update_service(db, dbservice, modification)
+ response = crud.update_service(db, dbservice, modification)
except sqlalchemy.exc.IntegrityError:
db.rollback()
- raise HTTPException(status_code=409, detail="Service by this name already exists")
+ raise HTTPException(status_code=409, detail="problem updating the service")
+ else:
+ for user in response.users:
+ await marznode.operations.update_user(user, old_inbounds=old_inbounds)
+ return response
@router.delete("/{id}")
diff --git a/app/routes/user.py b/app/routes/user.py
index 3ae7004..2d64498 100644
--- a/app/routes/user.py
+++ b/app/routes/user.py
@@ -82,14 +82,8 @@ async def modify_user(db_user: UserDep,
user = UserResponse.model_validate(db_user)
inbound_change = old_inbounds != new_inbounds
- if (user.status in {UserStatus.active, UserStatus.on_hold}
- and (not status_change or old_status == UserStatus.on_hold)):
- if inbound_change:
- await marznode.operations.update_user_inbounds(
- user=new_user, new_inbounds=new_inbounds, old_inbounds=old_inbounds)
- elif (user.status in {UserStatus.active, UserStatus.on_hold} and status_change and
- old_status not in {UserStatus.active, UserStatus.on_hold}):
- await marznode.operations.add_user(new_user)
+ if inbound_change and user.status in {UserStatus.active, UserStatus.on_hold}:
+ await marznode.operations.update_user(new_user, old_inbounds)
asyncio.create_task(report.user_updated(
user=user,
@@ -119,8 +113,7 @@ async def remove_user(db_user: UserDep,
"""
Remove a user
"""
- db_user.inbounds = []
- await marznode.operations.update_user(db_user)
+ await marznode.operations.remove_user(db_user)
crud.remove_user(db, db_user)
db.flush()
@@ -145,7 +138,7 @@ async def reset_user_data_usage(db_user: UserDep,
db_user = crud.reset_user_data_usage(db, db_user)
if db_user.status == UserStatus.active and previous_status == UserStatus.limited:
- await marznode.operations.add_user(db_user)
+ await marznode.operations.update_user(db_user)
user = UserResponse.model_validate(db_user)
asyncio.create_task(report.user_data_usage_reset(
@@ -168,7 +161,7 @@ async def revoke_user_subscription(db_user: UserDep,
if db_user.status in [UserStatus.active, UserStatus.on_hold]:
await marznode.operations.remove_user(db_user)
- await marznode.operations.add_user(db_user)
+ await marznode.operations.update_user(db_user)
user = UserResponse.model_validate(db_user)
asyncio.create_task(
report.user_subscription_revoked(
@@ -220,15 +213,11 @@ def get_users(db: DBDep,
async def reset_users_data_usage(db: DBDep,
admin: SudoAdminDep):
"""
- Reset all users data usage
+ Reset all users data usage,
+ You will need to restart for this to take effect for now
"""
dbadmin = crud.get_admin(db, admin.username)
crud.reset_all_users_data_usage(db=db, admin=dbadmin)
- # startup_config = xray.config.include_db_users()
- await xray.core.restart(xray.config.include_db_users(node_id=0))
- for node_id, node in list(xray.nodes.items()):
- if node.connected:
- xray.operations.restart_node(node_id, xray.config.include_db_users(node_id=node_id))
return {}
diff --git a/app/tasks/reset_user_data_usage.py b/app/tasks/reset_user_data_usage.py
index 196d66c..12c98fc 100644
--- a/app/tasks/reset_user_data_usage.py
+++ b/app/tasks/reset_user_data_usage.py
@@ -34,6 +34,6 @@ async def reset_user_data_usage():
crud.reset_user_data_usage(db, user)
# make user active if limited on usage reset
if user.status == UserStatus.active and old_status == UserStatus.limited:
- await marznode.operations.add_user(user)
+ await marznode.operations.update_user(user)
logger.info(f"User data usage reset for User \"{user.username}\"")