B23: политика паролей исполняется + ретенция журналов по-настоящему
- backend/password_policy.py: validate_new_password (длина, сложность буквы+цифры, сверка с текущим и историей), record_password_change (хранит ПРЕДЫДУШИЙ хэш, обрезка до password_history_count), password_expired + enforce_expiry (пометка must_change_password) - users.password_changed_at + таблица password_history (010_b23_policy) - change-password и админ-сброс теперь под полной политикой (сложность и переиспользование вместо голой длины); get_current_user проверяет срок действия каждого пароля при запросе - backend/purge_logs.py: реальный DELETE просроченных audit_events (+changes) и auth_events; POST /admin/users/maintenance/purge-logs (manage_security) + CLI python -m backend.purge_logs для cron - тесты: +19 (258 passed) — валидация/история/срок, purge/идемпотентность/403
This commit is contained in:
@@ -33,6 +33,8 @@ class User(Base):
|
||||
must_change_password = Column(Boolean, default=False)
|
||||
created_by = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"))
|
||||
updated_at = Column(DateTime, server_default=func.now())
|
||||
# B23: политика паролей (expiry/history исполняется в routers/auth.py)
|
||||
password_changed_at = Column(DateTime(timezone=True))
|
||||
|
||||
|
||||
class Case(Base):
|
||||
@@ -335,6 +337,21 @@ class SecuritySetting(Base):
|
||||
key = Column(String(50), primary_key=True)
|
||||
value = Column(String(255), nullable=False)
|
||||
|
||||
|
||||
class PasswordHistoryEntry(Base):
|
||||
"""B23: история паролей (bcrypt-хэши). Записывается при каждой смене,
|
||||
проверяется против password_history_count последних записей."""
|
||||
__tablename__ = "password_history"
|
||||
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
|
||||
hashed_password = Column(String(255), nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
__table_args__ = (
|
||||
sa.Index("idx_password_history_user", "user_id", "created_at"),
|
||||
)
|
||||
|
||||
# ==================== B21/E2: аудит действий ====================
|
||||
|
||||
class SearchOperation(Base):
|
||||
|
||||
Reference in New Issue
Block a user