fix(lint): format SNMP and credential profile files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-22 18:42:28 -05:00
parent e22163c55f
commit 231154d28b
8 changed files with 69 additions and 105 deletions

View File

@@ -41,12 +41,8 @@ def upgrade() -> None:
""")
)
conn.execute(
sa.text("ALTER TABLE credential_profiles ENABLE ROW LEVEL SECURITY")
)
conn.execute(
sa.text("ALTER TABLE credential_profiles FORCE ROW LEVEL SECURITY")
)
conn.execute(sa.text("ALTER TABLE credential_profiles ENABLE ROW LEVEL SECURITY"))
conn.execute(sa.text("ALTER TABLE credential_profiles FORCE ROW LEVEL SECURITY"))
conn.execute(
sa.text("""
@@ -63,20 +59,13 @@ def upgrade() -> None:
""")
)
conn.execute(
sa.text("GRANT SELECT ON credential_profiles TO poller_user")
)
conn.execute(
sa.text("GRANT SELECT, INSERT, UPDATE, DELETE ON credential_profiles TO app_user")
)
conn.execute(sa.text("GRANT SELECT ON credential_profiles TO poller_user"))
conn.execute(sa.text("GRANT SELECT, INSERT, UPDATE, DELETE ON credential_profiles TO app_user"))
def downgrade() -> None:
conn = op.get_bind()
conn.execute(
sa.text(
"DROP POLICY IF EXISTS credential_profiles_tenant_isolation"
" ON credential_profiles"
)
sa.text("DROP POLICY IF EXISTS credential_profiles_tenant_isolation ON credential_profiles")
)
op.drop_table("credential_profiles")

View File

@@ -630,12 +630,8 @@ def upgrade() -> None:
)
# -- RLS: system profiles visible to all tenants -----------------------
conn.execute(
sa.text("ALTER TABLE snmp_profiles ENABLE ROW LEVEL SECURITY")
)
conn.execute(
sa.text("ALTER TABLE snmp_profiles FORCE ROW LEVEL SECURITY")
)
conn.execute(sa.text("ALTER TABLE snmp_profiles ENABLE ROW LEVEL SECURITY"))
conn.execute(sa.text("ALTER TABLE snmp_profiles FORCE ROW LEVEL SECURITY"))
conn.execute(
sa.text("""
CREATE POLICY snmp_profiles_tenant_isolation
@@ -648,12 +644,8 @@ def upgrade() -> None:
""")
)
conn.execute(
sa.text("GRANT SELECT ON snmp_profiles TO poller_user")
)
conn.execute(
sa.text("GRANT SELECT, INSERT, UPDATE, DELETE ON snmp_profiles TO app_user")
)
conn.execute(sa.text("GRANT SELECT ON snmp_profiles TO poller_user"))
conn.execute(sa.text("GRANT SELECT, INSERT, UPDATE, DELETE ON snmp_profiles TO app_user"))
# -- Seed 6 system profiles --------------------------------------------
for profile in SEED_PROFILES:
@@ -679,10 +671,5 @@ def upgrade() -> None:
def downgrade() -> None:
conn = op.get_bind()
conn.execute(
sa.text(
"DROP POLICY IF EXISTS snmp_profiles_tenant_isolation"
" ON snmp_profiles"
)
)
conn.execute(sa.text("DROP POLICY IF EXISTS snmp_profiles_tenant_isolation ON snmp_profiles"))
op.drop_table("snmp_profiles")

View File

@@ -29,25 +29,12 @@ def upgrade() -> None:
conn.execute(sa.text("SET lock_timeout = '3s'"))
conn.execute(
sa.text(
"ALTER TABLE devices"
" ADD COLUMN device_type TEXT NOT NULL DEFAULT 'routeros'"
)
sa.text("ALTER TABLE devices ADD COLUMN device_type TEXT NOT NULL DEFAULT 'routeros'")
)
conn.execute(
sa.text(
"ALTER TABLE devices"
" ADD COLUMN snmp_port INTEGER DEFAULT 161"
)
)
conn.execute(sa.text("ALTER TABLE devices ADD COLUMN snmp_port INTEGER DEFAULT 161"))
conn.execute(
sa.text(
"ALTER TABLE devices"
" ADD COLUMN snmp_version TEXT"
)
)
conn.execute(sa.text("ALTER TABLE devices ADD COLUMN snmp_version TEXT"))
conn.execute(
sa.text(
@@ -69,18 +56,8 @@ def upgrade() -> None:
def downgrade() -> None:
conn = op.get_bind()
conn.execute(
sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS credential_profile_id")
)
conn.execute(
sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS snmp_profile_id")
)
conn.execute(
sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS snmp_version")
)
conn.execute(
sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS snmp_port")
)
conn.execute(
sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS device_type")
)
conn.execute(sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS credential_profile_id"))
conn.execute(sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS snmp_profile_id"))
conn.execute(sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS snmp_version"))
conn.execute(sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS snmp_port"))
conn.execute(sa.text("ALTER TABLE devices DROP COLUMN IF EXISTS device_type"))

View File

@@ -44,11 +44,7 @@ def upgrade() -> None:
conn.execute(sa.text("SELECT create_hypertable('snmp_metrics', 'time')"))
conn.execute(
sa.text(
"SELECT add_retention_policy('snmp_metrics', INTERVAL '90 days')"
)
)
conn.execute(sa.text("SELECT add_retention_policy('snmp_metrics', INTERVAL '90 days')"))
conn.execute(
sa.text("""
@@ -57,12 +53,8 @@ def upgrade() -> None:
""")
)
conn.execute(
sa.text("ALTER TABLE snmp_metrics ENABLE ROW LEVEL SECURITY")
)
conn.execute(
sa.text("ALTER TABLE snmp_metrics FORCE ROW LEVEL SECURITY")
)
conn.execute(sa.text("ALTER TABLE snmp_metrics ENABLE ROW LEVEL SECURITY"))
conn.execute(sa.text("ALTER TABLE snmp_metrics FORCE ROW LEVEL SECURITY"))
conn.execute(
sa.text("""
@@ -75,9 +67,7 @@ def upgrade() -> None:
""")
)
conn.execute(
sa.text("GRANT SELECT, INSERT ON snmp_metrics TO app_user")
)
conn.execute(sa.text("GRANT SELECT, INSERT ON snmp_metrics TO app_user"))
def downgrade() -> None:

View File

@@ -113,7 +113,10 @@ async def update_profile(
"""Update a credential profile. Requires operator role or above."""
await _check_tenant_access(current_user, tenant_id, db)
return await credential_profile_service.update_profile(
db=db, tenant_id=tenant_id, profile_id=profile_id, data=data,
db=db,
tenant_id=tenant_id,
profile_id=profile_id,
data=data,
user_id=current_user.user_id,
)
@@ -136,7 +139,9 @@ async def delete_profile(
"""
await _check_tenant_access(current_user, tenant_id, db)
await credential_profile_service.delete_profile(
db=db, tenant_id=tenant_id, profile_id=profile_id,
db=db,
tenant_id=tenant_id,
profile_id=profile_id,
user_id=current_user.user_id,
)

View File

@@ -31,7 +31,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.config import settings
from app.database import get_db
from app.middleware.rbac import require_operator_or_above, require_scope, require_tenant_admin_or_above
from app.middleware.rbac import (
require_operator_or_above,
require_scope,
require_tenant_admin_or_above,
)
from app.middleware.tenant_context import CurrentUser, get_current_user
from app.routers.devices import _check_tenant_access
from app.schemas.snmp_profile import (
@@ -252,7 +256,7 @@ async def update_profile(
sql = f"""
UPDATE snmp_profiles
SET {', '.join(set_clauses)}
SET {", ".join(set_clauses)}
WHERE id = :profile_id AND tenant_id = :tenant_id
RETURNING id, tenant_id, name, description, sys_object_id, vendor,
category, is_system, created_at, updated_at

View File

@@ -46,9 +46,7 @@ class CredentialProfileCreate(BaseModel):
@classmethod
def validate_credential_type(cls, v: str) -> str:
if v not in VALID_CREDENTIAL_TYPES:
raise ValueError(
f"credential_type must be one of: {', '.join(VALID_CREDENTIAL_TYPES)}"
)
raise ValueError(f"credential_type must be one of: {', '.join(VALID_CREDENTIAL_TYPES)}")
return v
@model_validator(mode="after")
@@ -141,9 +139,7 @@ class CredentialProfileUpdate(BaseModel):
if v is None:
return v
if v not in VALID_CREDENTIAL_TYPES:
raise ValueError(
f"credential_type must be one of: {', '.join(VALID_CREDENTIAL_TYPES)}"
)
raise ValueError(f"credential_type must be one of: {', '.join(VALID_CREDENTIAL_TYPES)}")
return v
@model_validator(mode="after")
@@ -151,9 +147,14 @@ class CredentialProfileUpdate(BaseModel):
"""Validate credential fields only when credential_type or credential fields change."""
# Collect which credential fields were provided
cred_fields = {
"username", "password", "community",
"security_level", "auth_protocol", "auth_passphrase",
"priv_protocol", "priv_passphrase",
"username",
"password",
"community",
"security_level",
"auth_protocol",
"auth_passphrase",
"priv_protocol",
"priv_passphrase",
}
has_cred_changes = any(getattr(self, f) is not None for f in cred_fields)

View File

@@ -65,7 +65,9 @@ def _build_credential_json(data: CredentialProfileCreate | CredentialProfileUpda
raise ValueError(f"Unknown credential_type: {ct}")
def _profile_response(profile: CredentialProfile, device_count: int = 0) -> CredentialProfileResponse:
def _profile_response(
profile: CredentialProfile, device_count: int = 0
) -> CredentialProfileResponse:
"""Build a CredentialProfileResponse from an ORM instance."""
return CredentialProfileResponse(
id=profile.id,
@@ -116,9 +118,11 @@ async def get_profiles(
credential_type: str | None = None,
) -> CredentialProfileListResponse:
"""List all credential profiles for a tenant."""
query = select(CredentialProfile).where(
CredentialProfile.tenant_id == tenant_id
).order_by(CredentialProfile.name)
query = (
select(CredentialProfile)
.where(CredentialProfile.tenant_id == tenant_id)
.order_by(CredentialProfile.name)
)
if credential_type:
query = query.where(CredentialProfile.credential_type == credential_type)
@@ -141,10 +145,7 @@ async def get_profiles(
for row in count_result:
device_counts[row.credential_profile_id] = row.cnt
responses = [
_profile_response(p, device_count=device_counts.get(p.id, 0))
for p in profiles
]
responses = [_profile_response(p, device_count=device_counts.get(p.id, 0)) for p in profiles]
return CredentialProfileListResponse(profiles=responses)
@@ -211,9 +212,14 @@ async def update_profile(
# Determine if credential re-encryption is needed
cred_fields = {
"username", "password", "community",
"security_level", "auth_protocol", "auth_passphrase",
"priv_protocol", "priv_passphrase",
"username",
"password",
"community",
"security_level",
"auth_protocol",
"auth_passphrase",
"priv_protocol",
"priv_passphrase",
}
has_cred_changes = any(getattr(data, f) is not None for f in cred_fields)
type_changed = data.credential_type is not None
@@ -241,13 +247,18 @@ async def update_profile(
action="credential_profile.update",
resource_type="credential_profile",
resource_id=str(profile.id),
details={"name": profile.name, "updated_fields": list(data.model_dump(exclude_unset=True).keys())},
details={
"name": profile.name,
"updated_fields": list(data.model_dump(exclude_unset=True).keys()),
},
)
return _profile_response(profile, device_count=dc)
def _merge_update(data: CredentialProfileUpdate, profile: CredentialProfile) -> CredentialProfileUpdate:
def _merge_update(
data: CredentialProfileUpdate, profile: CredentialProfile
) -> CredentialProfileUpdate:
"""For partial credential updates, overlay data onto existing profile type.
When credential_type is not changing but individual credential fields are,