diff --git a/backend/alembic/versions/0001_initial.py b/backend/alembic/versions/0001_initial.py index fb469cc..3739d22 100644 --- a/backend/alembic/versions/0001_initial.py +++ b/backend/alembic/versions/0001_initial.py @@ -30,7 +30,7 @@ def upgrade() -> None: "configs", sa.Column("id", sa.Integer, primary_key=True), sa.Column("name", sa.String(128), nullable=False), - sa.Column("description", sa.Text, server_default=""), + sa.Column("description", sa.Text, server_default="''"), sa.Column("is_active", sa.Boolean, server_default="true"), sa.Column("created_at", sa.DateTime, server_default=sa.func.now()), sa.Column("updated_at", sa.DateTime, server_default=sa.func.now()), @@ -42,7 +42,7 @@ def upgrade() -> None: sa.Column("config_id", sa.Integer, sa.ForeignKey("configs.id"), nullable=False), sa.Column("name", sa.String(32), nullable=False), sa.Column("type", sa.String(16), nullable=False), - sa.Column("options", sa.Text, server_default=""), + sa.Column("options", sa.Text, server_default="''"), sa.UniqueConstraint("config_id", "name", name="uq_zone_name_per_config"), ) op.create_table( @@ -51,7 +51,7 @@ def upgrade() -> None: sa.Column("config_id", sa.Integer, sa.ForeignKey("configs.id"), nullable=False), sa.Column("name", sa.String(32), nullable=False), sa.Column("zone_id", sa.Integer, sa.ForeignKey("zones.id"), nullable=False), - sa.Column("options", sa.Text, server_default=""), + sa.Column("options", sa.Text, server_default="''"), ) op.create_table( "policies", @@ -60,8 +60,8 @@ def upgrade() -> None: sa.Column("src_zone_id", sa.Integer, sa.ForeignKey("zones.id"), nullable=False), sa.Column("dst_zone_id", sa.Integer, sa.ForeignKey("zones.id"), nullable=False), sa.Column("policy", sa.String(16), nullable=False), - sa.Column("log_level", sa.String(16), server_default=""), - sa.Column("comment", sa.Text, server_default=""), + sa.Column("log_level", sa.String(16), server_default="''"), + sa.Column("comment", sa.Text, server_default="''"), sa.Column("position", sa.Integer, server_default="0"), ) op.create_table( @@ -71,12 +71,12 @@ def upgrade() -> None: sa.Column("action", sa.String(32), nullable=False), sa.Column("src_zone_id", sa.Integer, sa.ForeignKey("zones.id"), nullable=True), sa.Column("dst_zone_id", sa.Integer, sa.ForeignKey("zones.id"), nullable=True), - sa.Column("src_ip", sa.String(64), server_default=""), - sa.Column("dst_ip", sa.String(64), server_default=""), - sa.Column("proto", sa.String(16), server_default=""), - sa.Column("dport", sa.String(64), server_default=""), - sa.Column("sport", sa.String(64), server_default=""), - sa.Column("comment", sa.Text, server_default=""), + sa.Column("src_ip", sa.String(64), server_default="''"), + sa.Column("dst_ip", sa.String(64), server_default="''"), + sa.Column("proto", sa.String(16), server_default="''"), + sa.Column("dport", sa.String(64), server_default="''"), + sa.Column("sport", sa.String(64), server_default="''"), + sa.Column("comment", sa.Text, server_default="''"), sa.Column("position", sa.Integer, server_default="0"), ) op.create_table( @@ -85,8 +85,8 @@ def upgrade() -> None: sa.Column("config_id", sa.Integer, sa.ForeignKey("configs.id"), nullable=False), sa.Column("source_network", sa.String(64), nullable=False), sa.Column("out_interface", sa.String(32), nullable=False), - sa.Column("to_address", sa.String(64), server_default=""), - sa.Column("comment", sa.Text, server_default=""), + sa.Column("to_address", sa.String(64), server_default="''"), + sa.Column("comment", sa.Text, server_default="''"), ) # --- Seed data --- diff --git a/backend/app/api/configs.py b/backend/app/api/configs.py index 8a06220..cb029fa 100644 --- a/backend/app/api/configs.py +++ b/backend/app/api/configs.py @@ -82,7 +82,7 @@ def generate_config( format: str = "json", db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user), -) -> Response: +): config = ( db.query(models.Config) .options( diff --git a/frontend/src/store/auth.ts b/frontend/src/store/auth.ts index fdb4721..da67465 100644 --- a/frontend/src/store/auth.ts +++ b/frontend/src/store/auth.ts @@ -10,20 +10,22 @@ export interface User { // Simple module-level state (no external lib needed) let currentUser: User | null = null +let isLoading = true +let fetchPromise: Promise | null = null const listeners = new Set<() => void>() export function useAuth() { const [user, setUser] = useState(currentUser) - const [loading, setLoading] = useState(currentUser === null) + const [loading, setLoading] = useState(isLoading) useEffect(() => { - const update = () => setUser(currentUser) + const update = () => { setUser(currentUser); setLoading(isLoading) } listeners.add(update) - if (currentUser === null) { - authApi.me() - .then((res) => { currentUser = res.data; listeners.forEach((l) => l()) }) - .catch(() => { currentUser = null; listeners.forEach((l) => l()) }) - .finally(() => setLoading(false)) + if (!fetchPromise) { + fetchPromise = authApi.me() + .then((res) => { currentUser = res.data }) + .catch(() => { currentUser = null }) + .finally(() => { isLoading = false; listeners.forEach((l) => l()) }) } return () => { listeners.delete(update) } }, [])