Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: float bug when creating users and showing float data #1541

Merged
merged 3 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ class User(Base):
)

@hybrid_property
def reseted_usage(self):
return sum([log.used_traffic_at_reset for log in self.usage_logs])
def reseted_usage(self) -> int:
return int(sum([log.used_traffic_at_reset for log in self.usage_logs]))

@reseted_usage.expression
def reseted_usage(cls):
Expand All @@ -115,8 +115,8 @@ def reseted_usage(cls):
)

@property
def lifetime_used_traffic(self):
return (
def lifetime_used_traffic(self) -> int:
return int(
sum([log.used_traffic_at_reset for log in self.usage_logs])
+ self.used_traffic
)
Expand Down
12 changes: 11 additions & 1 deletion app/models/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from passlib.context import CryptContext
from pydantic import ConfigDict, field_validator, BaseModel
from pydantic import BaseModel, ConfigDict, field_validator

from app.db import Session, crud, get_db
from app.utils.jwt import get_admin_payload
Expand All @@ -26,6 +26,16 @@ class Admin(BaseModel):
users_usage: Optional[int] = None
model_config = ConfigDict(from_attributes=True)

@field_validator("users_usage", mode='before')
def cast_to_int(cls, v):
if v is None: # Allow None values
return v
if isinstance(v, float): # Allow float to int conversion
return int(v)
if isinstance(v, int): # Allow integers directly
return v
raise ValueError("must be an integer or a float, not a string") # Reject strings

@classmethod
def get_admin(cls, token: str, db: Session):
payload = get_admin_payload(token)
Expand Down
30 changes: 30 additions & 0 deletions app/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ class User(BaseModel):

next_plan: Optional[NextPlanModel] = Field(None, nullable=True)

@field_validator('data_limit', mode='before')
def cast_to_int(cls, v):
if v is None: # Allow None values
return v
if isinstance(v, float): # Allow float to int conversion
return int(v)
if isinstance(v, int): # Allow integers directly
return v
raise ValueError("data_limit must be an integer or a float, not a string") # Reject strings

@field_validator("proxies", mode="before")
def validate_proxies(cls, v, values, **kwargs):
if not v:
Expand Down Expand Up @@ -306,6 +316,16 @@ def validate_proxies(cls, v, values, **kwargs):
v = {p.type: p.settings for p in v}
return super().validate_proxies(v, values, **kwargs)

@field_validator("used_traffic", "lifetime_used_traffic", mode='before')
def cast_to_int(cls, v):
if v is None: # Allow None values
return v
if isinstance(v, float): # Allow float to int conversion
return int(v)
if isinstance(v, int): # Allow integers directly
return v
raise ValueError("must be an integer or a float, not a string") # Reject strings


class SubscriptionUserResponse(UserResponse):
admin: Admin | None = Field(default=None, exclude=True)
Expand All @@ -326,6 +346,16 @@ class UserUsageResponse(BaseModel):
node_name: str
used_traffic: int

@field_validator("used_traffic", mode='before')
def cast_to_int(cls, v):
if v is None: # Allow None values
return v
if isinstance(v, float): # Allow float to int conversion
return int(v)
if isinstance(v, int): # Allow integers directly
return v
raise ValueError("must be an integer or a float, not a string") # Reject strings


class UserUsagesResponse(BaseModel):
username: str
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ psutil==5.9.4
pyOpenSSL==24.2.1
PySocks==1.7.1
pyTelegramBotAPI==4.9.0
pydantic==2.10.3
pydantic==2.10.4
python-dateutil==2.8.2
python-decouple==3.6
python-dotenv==0.21.1
Expand Down