Files
OpenVPN-Monitoring-Simple/APP_PROFILER/schemas.py
T
iclaoudezinandClaude Sonnet 5.5 11c1b6379b Harden auth and API: username change, 2FA fixes, input validation
- Add POST /api/auth/change-username (password + OTP when 2FA is on,
  format/reserved-name checks, uniqueness) and a Change Username modal
  in Account.vue; use the real username for the 2FA provisioning URI.
- Stop creating the built-in admin/password user; the initial admin is
  seeded only from OVPMON_INITIAL_ADMIN_USER/PASSWORD.
- Reject 2FA-pending temporary tokens on all protected routes (Flask
  token_required, Profiler verify_token); only /api/auth/verify-2fa
  accepts them.
- Stop logging the OTP and TOTP secret in enable_2fa.
- Profiler: validate profile username (pattern + realpath checks in
  schema, router, pki and generator) to prevent path traversal.
- Restrict CORS to the panel origin in Profiler and Flask APIs.
- UI: header username no longer sticks to the hardcoded Admin fallback;
  it is synced from /user/me and updated after a rename.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 12:03:36 +00:00

87 lines
2.5 KiB
Python

from pydantic import BaseModel, Field
from typing import List, Optional, Literal
from datetime import datetime
# --- PKI Settings Schemas ---
class PKISettingBase(BaseModel):
fqdn_ca: str = "ovpn-ca"
fqdn_server: str = "ovpn-srv"
easyrsa_dn: str = "cn_only"
easyrsa_req_country: str = "RU"
easyrsa_req_province: str = "Moscow"
easyrsa_req_city: str = "Moscow"
easyrsa_req_org: str = "SomeORG"
easyrsa_req_email: str = "info@someorg.local"
easyrsa_req_ou: str = "IT"
easyrsa_key_size: int = 2048
easyrsa_ca_expire: int = 3650
easyrsa_cert_expire: int = 3649
easyrsa_cert_renew: int = 30
easyrsa_crl_days: int = 3649
easyrsa_batch: bool = True
class PKISettingUpdate(PKISettingBase):
pass
class PKISetting(PKISettingBase):
id: int
class Config:
from_attributes = True
# --- System Settings Schemas ---
class SystemSettingsBase(BaseModel):
protocol: Literal['tcp', 'udp'] = "udp"
port: int = 1194
vpn_network: str = "172.20.1.0"
vpn_netmask: str = "255.255.255.0"
tunnel_type: Literal['FULL', 'SPLIT'] = "FULL"
split_routes: List[str] = Field(default_factory=list)
duplicate_cn: bool = False
crl_verify: bool = False
client_to_client: bool = False
user_defined_dns: bool = False
dns_servers: List[str] = Field(default_factory=list)
user_defined_cdscripts: bool = False
connect_script: str = ""
disconnect_script: str = ""
management_interface: bool = False
management_interface_address: str = "127.0.0.1"
management_interface_address: str = "127.0.0.1"
management_port: int = 7505
public_ip: Optional[str] = None
tun_mtu: Optional[int] = None
mssfix: Optional[int] = None
class SystemSettingsUpdate(SystemSettingsBase):
pass
class SystemSettings(SystemSettingsBase):
id: int
class Config:
from_attributes = True
class ConfigResponse(BaseModel):
server: Optional[SystemSettings] = None
pki: Optional[PKISetting] = None
# --- User Profile Schemas ---
class UserProfileBase(BaseModel):
username: str = Field(..., pattern=r"^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$")
class UserProfileCreate(UserProfileBase):
pass
class UserProfile(UserProfileBase):
id: int
status: str
created_at: datetime
revoked_at: Optional[datetime] = None
expiration_date: Optional[datetime] = None
days_remaining: Optional[int] = None
is_revoked: bool = False
is_expired: bool = False
file_path: Optional[str] = None
class Config:
from_attributes = True