enable policies

This commit is contained in:
2026-01-16 17:31:20 +10:30
parent b2e084db33
commit d063a0ca81
28 changed files with 4296 additions and 224 deletions
+36
View File
@@ -9,6 +9,7 @@ class UserStatus(str, Enum):
INACTIVE = "inactive"
SUSPENDED = "suspended"
PENDING = "pending"
COMPLIANCE_SUSPENDED = "compliance_suspended"
class OrganizationRole(str, Enum):
@@ -86,6 +87,12 @@ class AuditAction(str, Enum):
WEBAUTHN_CREDENTIAL_DELETED = "webauthn.credential.deleted"
WEBAUTHN_CREDENTIAL_RENAMED = "webauthn.credential.renamed"
# Security policy actions
ORG_SECURITY_POLICY_UPDATE = "org.security_policy.update"
USER_SECURITY_POLICY_OVERRIDE_UPDATE = "user.security_policy.override_update"
MFA_POLICY_USER_SUSPENDED = "mfa.policy.user_suspended"
MFA_POLICY_USER_COMPLIANT = "mfa.policy.user_compliant"
class OIDCGrantType(str, Enum):
"""OIDC grant types."""
@@ -116,3 +123,32 @@ class ErrorType:
RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED"
INTERNAL_ERROR = "INTERNAL_ERROR"
BAD_REQUEST = "BAD_REQUEST"
class MfaPolicyMode(str, Enum):
"""MFA policy mode for organizations."""
DISABLED = "disabled"
OPTIONAL = "optional"
REQUIRE_TOTP = "require_totp"
REQUIRE_WEBAUTHN = "require_webauthn"
REQUIRE_TOTP_OR_WEBAUTHN = "require_totp_or_webauthn"
class MfaComplianceStatus(str, Enum):
"""MFA compliance status for users per organization."""
NOT_APPLICABLE = "not_applicable"
PENDING = "pending"
IN_GRACE = "in_grace"
COMPLIANT = "compliant"
PAST_DUE = "past_due"
SUSPENDED = "suspended"
class MfaRequirementOverride(str, Enum):
"""User override for organization MFA requirements."""
INHERIT = "inherit"
REQUIRED = "required"
EXEMPT = "exempt"
+40 -1
View File
@@ -2,7 +2,8 @@
from functools import wraps
from flask import request, g
from gatehouse_app.utils.response import api_response
from gatehouse_app.utils.constants import OrganizationRole
from gatehouse_app.utils.constants import OrganizationRole, UserStatus
from gatehouse_app.exceptions.auth_exceptions import UnauthorizedError, ForbiddenError
def login_required(f):
@@ -127,3 +128,41 @@ def require_owner(f):
def require_admin(f):
"""Decorator to require organization admin or owner role."""
return require_role(OrganizationRole.OWNER, OrganizationRole.ADMIN)(f)
def full_access_required(f):
"""Decorator to require full access session (not compliance-only).
This decorator checks if the user has a compliance-only session or
is in COMPLIANCE_SUSPENDED status. If so, it returns a 403 error
with error_type "MFA_COMPLIANCE_REQUIRED".
Use this decorator on endpoints that require full MFA compliance.
Endpoints for MFA enrollment, status, and logout should NOT use this decorator.
"""
@wraps(f)
def decorated_function(*args, **kwargs):
user = getattr(g, "current_user", None)
session = getattr(g, "current_session", None)
if not user or not session:
return api_response(
success=False,
message="Authentication required",
status=401,
error_type="AUTH_REQUIRED",
)
# Check for compliance-only session or compliance suspended status
if session.is_compliance_only or user.status == UserStatus.COMPLIANCE_SUSPENDED:
return api_response(
success=False,
message="MFA compliance required to access this resource",
status=403,
error_type="MFA_COMPLIANCE_REQUIRED",
error_details={"overall_status": "suspended"},
)
return f(*args, **kwargs)
return decorated_function