se agregaron nuevas caracteristicas
This commit is contained in:
+133
-20
@@ -10,7 +10,8 @@ from app.core.security import generate_registration_code, generate_device_token,
|
||||
from app.models.models import User, Client, ClientCredential, RegistrationCode
|
||||
from app.schemas.schemas import (
|
||||
ClientResponse, ClientRegisterRequest, ClientRegisterResponse,
|
||||
RegistrationCodeCreate, RegistrationCodeResponse, ClientHeartbeatRequest
|
||||
RegistrationCodeCreate, RegistrationCodeResponse, ClientHeartbeatRequest,
|
||||
ClientUpdateRequest
|
||||
)
|
||||
from app.api.deps import get_current_user, require_admin, get_current_client
|
||||
from app.services.event_service import log_event
|
||||
@@ -78,27 +79,55 @@ async def register_client(
|
||||
detail="Invalid, expired, or already used registration code."
|
||||
)
|
||||
|
||||
# Determine next client code (e.g., CLIENT-0001)
|
||||
count_res = await db.execute(select(func.count(Client.id)))
|
||||
client_count = count_res.scalar() or 0
|
||||
client_code = f"CLIENT-{client_count + 1:04d}"
|
||||
|
||||
client_ip = request.client.host if request.client else None
|
||||
|
||||
# Create Client
|
||||
client = Client(
|
||||
client_code=client_code,
|
||||
name=payload.name or reg_code.client_name_hint or payload.hostname,
|
||||
hostname=payload.hostname,
|
||||
os_info=payload.os_info,
|
||||
ip_address=client_ip,
|
||||
agent_version=payload.agent_version,
|
||||
status="ONLINE",
|
||||
last_seen_at=now,
|
||||
is_active=True
|
||||
)
|
||||
db.add(client)
|
||||
await db.flush()
|
||||
if reg_code.client_id:
|
||||
# Re-registering an existing client!
|
||||
client_res = await db.execute(select(Client).where(Client.id == reg_code.client_id))
|
||||
client = client_res.scalar_one_or_none()
|
||||
if not client:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Client associated with this registration code not found."
|
||||
)
|
||||
# Update connection info and mark as active
|
||||
client.hostname = payload.hostname
|
||||
client.os_info = payload.os_info
|
||||
client.ip_address = client_ip
|
||||
client.agent_version = payload.agent_version
|
||||
client.status = "ONLINE"
|
||||
client.last_seen_at = now
|
||||
client.is_active = True
|
||||
else:
|
||||
# Create a new Client
|
||||
max_id_res = await db.execute(select(func.max(Client.id)))
|
||||
max_id = max_id_res.scalar() or 0
|
||||
client_code = f"CLIENT-{max_id + 1:04d}"
|
||||
|
||||
# Load default client quota from settings
|
||||
from app.services.settings_service import get_setting
|
||||
default_quota_gb_str = await get_setting(db, "default_client_quota_gb")
|
||||
default_quota_bytes = 100 * 1024 * 1024 * 1024
|
||||
if default_quota_gb_str:
|
||||
try:
|
||||
default_quota_bytes = int(default_quota_gb_str) * 1024 * 1024 * 1024
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
client = Client(
|
||||
client_code=client_code,
|
||||
name=payload.name or reg_code.client_name_hint or payload.hostname,
|
||||
hostname=payload.hostname,
|
||||
os_info=payload.os_info,
|
||||
ip_address=client_ip,
|
||||
agent_version=payload.agent_version,
|
||||
status="ONLINE",
|
||||
last_seen_at=now,
|
||||
is_active=True,
|
||||
storage_quota_bytes=default_quota_bytes
|
||||
)
|
||||
db.add(client)
|
||||
await db.flush()
|
||||
|
||||
# Generate device unique ID and secret token
|
||||
device_id = str(uuid.uuid4())
|
||||
@@ -220,6 +249,90 @@ async def revoke_client_credentials(
|
||||
|
||||
return {"message": "Client credentials successfully revoked"}
|
||||
|
||||
@router.post("/{client_id}/re-register", response_model=RegistrationCodeResponse)
|
||||
async def generate_client_re_registration_code(
|
||||
client_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
admin_user: User = Depends(require_admin)
|
||||
):
|
||||
"""Generates a registration code to re-link an existing client's agent."""
|
||||
client_res = await db.execute(select(Client).where(Client.id == client_id))
|
||||
client = client_res.scalar_one_or_none()
|
||||
if not client:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Client not found"
|
||||
)
|
||||
|
||||
# Revoke old credentials to prepare for the new agent connection
|
||||
cred_res = await db.execute(select(ClientCredential).where(ClientCredential.client_id == client_id))
|
||||
creds = cred_res.scalars().all()
|
||||
for cred in creds:
|
||||
cred.is_revoked = True
|
||||
|
||||
code_str = generate_registration_code()
|
||||
expires = datetime.now(timezone.utc) + timedelta(hours=24) # 24 hours to re-register
|
||||
|
||||
reg_code = RegistrationCode(
|
||||
code=code_str,
|
||||
client_id=client.id,
|
||||
client_name_hint=client.name,
|
||||
expires_at=expires,
|
||||
is_used=False
|
||||
)
|
||||
db.add(reg_code)
|
||||
await db.commit()
|
||||
await db.refresh(reg_code)
|
||||
|
||||
await log_event(
|
||||
db=db,
|
||||
event_type="REGISTRATION_CODE_GENERATED",
|
||||
message=f"Generated re-registration code {code_str} for client {client.name} ({client.client_code}).",
|
||||
severity="INFO",
|
||||
client_id=client_id,
|
||||
user_email=admin_user.email
|
||||
)
|
||||
|
||||
return reg_code
|
||||
|
||||
@router.patch("/{client_id}", response_model=ClientResponse)
|
||||
async def update_client(
|
||||
client_id: int,
|
||||
payload: ClientUpdateRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
admin_user: User = Depends(require_admin)
|
||||
):
|
||||
"""Updates client details such as alias."""
|
||||
res = await db.execute(select(Client).where(Client.id == client_id))
|
||||
client = res.scalar_one_or_none()
|
||||
if not client:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Client not found")
|
||||
|
||||
if payload.alias is not None:
|
||||
client.alias = payload.alias
|
||||
if payload.storage_quota_bytes is not None:
|
||||
client.storage_quota_bytes = payload.storage_quota_bytes
|
||||
|
||||
await db.commit()
|
||||
await db.refresh(client)
|
||||
|
||||
message_parts = []
|
||||
if payload.alias is not None:
|
||||
message_parts.append(f"alias to '{client.alias}'")
|
||||
if payload.storage_quota_bytes is not None:
|
||||
message_parts.append(f"quota to {client.storage_quota_bytes} bytes")
|
||||
|
||||
await log_event(
|
||||
db=db,
|
||||
event_type="CLIENT_UPDATED",
|
||||
message=f"Updated client {client.client_code}: {', '.join(message_parts)}.",
|
||||
severity="INFO",
|
||||
client_id=client.id,
|
||||
user_email=admin_user.email
|
||||
)
|
||||
|
||||
return client
|
||||
|
||||
@router.delete("/{client_id}")
|
||||
async def delete_client(
|
||||
client_id: int,
|
||||
|
||||
Reference in New Issue
Block a user