Add superadmin routes to API
This commit is contained in:
@@ -283,7 +283,8 @@ def admin_verify_user_email(user_id):
|
||||
if was_inactive:
|
||||
target.status = UserStatus.ACTIVE
|
||||
|
||||
EmailVerificationToken.query.filter_by(user_id=target.id, used_at=None).delete()
|
||||
now = datetime.now(timezone.utc)
|
||||
EmailVerificationToken.query.filter_by(user_id=target.id, used_at=None).filter(EmailVerificationToken.deleted_at == None).update({"deleted_at": now}, synchronize_session=False)
|
||||
_db.session.commit()
|
||||
|
||||
AuditService.log_action(
|
||||
@@ -300,14 +301,12 @@ def admin_verify_user_email(user_id):
|
||||
@api_v1_bp.route("/admin/users/<user_id>/delete", methods=["POST"])
|
||||
@login_required
|
||||
@full_access_required
|
||||
def admin_hard_delete_user(user_id):
|
||||
def admin_delete_user(user_id):
|
||||
from gatehouse_app.models.organization.organization_member import OrganizationMember
|
||||
from gatehouse_app.models.user.user import User as _User
|
||||
from gatehouse_app.models.ssh_ca.ssh_key import SSHKey
|
||||
from gatehouse_app.models.ssh_ca.ssh_certificate import SSHCertificate
|
||||
from gatehouse_app.models.ssh_ca.certificate_audit_log import CertificateAuditLog
|
||||
from gatehouse_app.models.auth.authentication_method import OAuthState
|
||||
from gatehouse_app.models.security.organization_security_policy import OrganizationSecurityPolicy
|
||||
from gatehouse_app.extensions import db as _db
|
||||
from gatehouse_app.utils.constants import AuditAction, OrganizationRole
|
||||
from gatehouse_app.services.audit_service import AuditService
|
||||
@@ -373,44 +372,29 @@ def admin_hard_delete_user(user_id):
|
||||
|
||||
target_email = target.email
|
||||
target_id_str = str(target.id)
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
try:
|
||||
# NULL out FK references that don't cascade on delete so the
|
||||
# session.delete() below doesn't hit FK constraint violations.
|
||||
# Soft delete the user — set deleted_at timestamp.
|
||||
target.deleted_at = now
|
||||
|
||||
# org_invite_tokens.invited_by_id — SET NULL is already on the FK column,
|
||||
# but OrganizationMember.invited_by_id has no ondelete clause.
|
||||
_db.session.execute(
|
||||
_db.text("UPDATE organization_members SET invited_by_id = NULL WHERE invited_by_id = :uid"),
|
||||
{"uid": target_id_str},
|
||||
# Soft delete associated OAuthState records.
|
||||
OAuthState.query.filter_by(user_id=target_id_str).filter(OAuthState.deleted_at == None).update(
|
||||
{"deleted_at": now}, synchronize_session=False
|
||||
)
|
||||
|
||||
# certificate_audit_logs.user_id — nullable, no ondelete clause.
|
||||
CertificateAuditLog.query.filter_by(user_id=target_id_str).update(
|
||||
{"user_id": None}, synchronize_session=False
|
||||
)
|
||||
|
||||
# organization_security_policies.updated_by_user_id — nullable, no ondelete.
|
||||
OrganizationSecurityPolicy.query.filter_by(updated_by_user_id=target_id_str).update(
|
||||
{"updated_by_user_id": None}, synchronize_session=False
|
||||
)
|
||||
|
||||
# oauth_states.user_id — nullable, no ondelete.
|
||||
OAuthState.query.filter_by(user_id=target_id_str).delete(synchronize_session=False)
|
||||
|
||||
_db.session.delete(target)
|
||||
_db.session.flush()
|
||||
except Exception as exc:
|
||||
_db.session.rollback()
|
||||
_logger.error(f"Hard delete failed for {target_id_str}: {exc}")
|
||||
_logger.error(f"Soft delete failed for {target_id_str}: {exc}")
|
||||
return api_response(success=False, message="Failed to delete user account. Please try again.", status=500, error_type="SERVER_ERROR")
|
||||
|
||||
AuditService.log_action(
|
||||
action=AuditAction.USER_HARD_DELETE,
|
||||
action=AuditAction.USER_DELETE,
|
||||
user_id=caller.id,
|
||||
organization_id=admin_in_shared_org.organization_id,
|
||||
resource_type="user", resource_id=target_id_str,
|
||||
description=f"Admin permanently deleted user account: {target_email}",
|
||||
description=f"Admin deleted user account: {target_email}",
|
||||
metadata={
|
||||
"deleted_user_id": target_id_str, "deleted_user_email": target_email,
|
||||
"ssh_keys_deleted": ssh_key_count, "certs_revoked": active_cert_count,
|
||||
@@ -419,7 +403,7 @@ def admin_hard_delete_user(user_id):
|
||||
|
||||
_db.session.commit()
|
||||
return api_response(
|
||||
message=f"User account {target_email} has been permanently deleted.",
|
||||
message=f"User account {target_email} has been deleted.",
|
||||
data={"deleted_user_id": target_id_str, "deleted_user_email": target_email,
|
||||
"ssh_keys_deleted": ssh_key_count, "certs_revoked": active_cert_count},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user