支持删除CA和证书
This commit is contained in:
parent
dac0655cff
commit
c390c63323
121
app.py
121
app.py
@ -1049,6 +1049,127 @@ def export_certificate_view(cert_id):
|
||||
|
||||
return render_template('export_certificate.html', cert=cert)
|
||||
|
||||
# 在app.py中添加以下路由
|
||||
|
||||
@app.route('/cas/<int:ca_id>/delete', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def delete_ca(ca_id):
|
||||
ca = get_ca_by_id(ca_id)
|
||||
if not ca:
|
||||
flash('CA不存在', 'danger')
|
||||
return redirect(url_for('ca_list'))
|
||||
|
||||
# 检查权限
|
||||
if not current_user.is_admin and ca['created_by'] != current_user.id:
|
||||
flash('无权删除此CA', 'danger')
|
||||
return redirect(url_for('ca_list'))
|
||||
|
||||
# 检查是否有关联的证书
|
||||
conn = get_db_connection()
|
||||
if conn:
|
||||
try:
|
||||
cursor = conn.cursor(dictionary=True)
|
||||
cursor.execute("SELECT COUNT(*) as count FROM certificates WHERE ca_id = %s", (ca_id,))
|
||||
result = cursor.fetchone()
|
||||
if result['count'] > 0:
|
||||
flash('无法删除CA,因为存在关联的证书', 'danger')
|
||||
return redirect(url_for('ca_detail', ca_id=ca_id))
|
||||
except Error as e:
|
||||
print(f"Database error: {e}")
|
||||
flash('检查关联证书失败', 'danger')
|
||||
return redirect(url_for('ca_detail', ca_id=ca_id))
|
||||
finally:
|
||||
if conn.is_connected():
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
if request.method == 'POST':
|
||||
# 删除文件
|
||||
try:
|
||||
if os.path.exists(ca['cert_path']):
|
||||
os.remove(ca['cert_path'])
|
||||
if os.path.exists(ca['key_path']):
|
||||
os.remove(ca['key_path'])
|
||||
# 删除CA目录
|
||||
ca_dir = os.path.dirname(ca['cert_path'])
|
||||
if os.path.exists(ca_dir):
|
||||
os.rmdir(ca_dir)
|
||||
except OSError as e:
|
||||
print(f"文件删除错误: {e}")
|
||||
flash('删除文件时出错', 'danger')
|
||||
return redirect(url_for('ca_detail', ca_id=ca_id))
|
||||
|
||||
# 删除数据库记录
|
||||
conn = get_db_connection()
|
||||
if conn:
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DELETE FROM certificate_authorities WHERE id = %s", (ca_id,))
|
||||
conn.commit()
|
||||
flash('CA删除成功', 'success')
|
||||
return redirect(url_for('ca_list'))
|
||||
except Error as e:
|
||||
print(f"Database error: {e}")
|
||||
flash('删除CA记录失败', 'danger')
|
||||
return redirect(url_for('ca_detail', ca_id=ca_id))
|
||||
finally:
|
||||
if conn.is_connected():
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
return render_template('confirm_delete_ca.html', ca=ca)
|
||||
|
||||
|
||||
@app.route('/certificates/<int:cert_id>/delete', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def delete_certificate(cert_id):
|
||||
cert = get_certificate_by_id(cert_id)
|
||||
if not cert:
|
||||
flash('证书不存在', 'danger')
|
||||
return redirect(url_for('certificate_list'))
|
||||
|
||||
# 检查权限
|
||||
if not current_user.is_admin and cert['created_by'] != current_user.id:
|
||||
flash('无权删除此证书', 'danger')
|
||||
return redirect(url_for('certificate_list'))
|
||||
|
||||
if request.method == 'POST':
|
||||
# 删除文件
|
||||
try:
|
||||
if os.path.exists(cert['cert_path']):
|
||||
os.remove(cert['cert_path'])
|
||||
if os.path.exists(cert['key_path']):
|
||||
os.remove(cert['key_path'])
|
||||
if os.path.exists(cert['csr_path']):
|
||||
os.remove(cert['csr_path'])
|
||||
# 删除证书目录
|
||||
cert_dir = os.path.dirname(cert['cert_path'])
|
||||
if os.path.exists(cert_dir):
|
||||
os.rmdir(cert_dir)
|
||||
except OSError as e:
|
||||
print(f"文件删除错误: {e}")
|
||||
flash('删除文件时出错', 'danger')
|
||||
return redirect(url_for('certificate_detail', cert_id=cert_id))
|
||||
|
||||
# 删除数据库记录
|
||||
conn = get_db_connection()
|
||||
if conn:
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("DELETE FROM certificates WHERE id = %s", (cert_id,))
|
||||
conn.commit()
|
||||
flash('证书删除成功', 'success')
|
||||
return redirect(url_for('certificate_list'))
|
||||
except Error as e:
|
||||
print(f"Database error: {e}")
|
||||
flash('删除证书记录失败', 'danger')
|
||||
return redirect(url_for('certificate_detail', cert_id=cert_id))
|
||||
finally:
|
||||
if conn.is_connected():
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
return render_template('confirm_delete_certificate.html', cert=cert)
|
||||
|
||||
def generate_separate_files_zip(cert, cert_ext, zip_suffix):
|
||||
"""生成包含分开文件的ZIP包通用函数"""
|
||||
|
||||
@ -28,6 +28,12 @@
|
||||
<i class="fas fa-download me-1"></i> 下载CRL
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{{ url_for('delete_ca', ca_id=ca.id) }}"
|
||||
class="btn btn-danger me-2"
|
||||
data-bs-toggle="tooltip"
|
||||
title="删除此CA(谨慎操作)">
|
||||
<i class="fas fa-trash-alt me-1"></i> 删除CA
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
{% endif %}
|
||||
<a href="{{ url_for('renew_certificate_view', cert_id=cert.id) }}" class="btn btn-primary me-2">续期</a>
|
||||
<a href="{{ url_for('export_certificate_view', cert_id=cert.id) }}" class="btn btn-success">导出</a>
|
||||
<a href="{{ url_for('delete_certificate', cert_id=cert.id) }}" class="btn btn-danger">删除</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
40
templates/confirm_delete_ca.html
Normal file
40
templates/confirm_delete_ca.html
Normal file
@ -0,0 +1,40 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}删除CA - {{ ca.name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="card border-danger">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h4><i class="fas fa-exclamation-triangle me-2"></i> 确认删除CA</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">您确定要删除以下CA吗?</h5>
|
||||
<div class="alert alert-danger">
|
||||
<strong>警告:</strong>此操作不可逆!所有与此CA相关的文件将被永久删除。
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h6>CA信息:</h6>
|
||||
<ul>
|
||||
<li>名称: {{ ca.name }}</li>
|
||||
<li>通用名: {{ ca.common_name }}</li>
|
||||
<li>组织: {{ ca.organization }}</li>
|
||||
<li>创建时间: {{ ca.created_at.strftime('%Y-%m-%d %H:%M') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url_for('delete_ca', ca_id=ca.id) }}">
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{{ url_for('ca_detail', ca_id=ca.id) }}" class="btn btn-secondary">
|
||||
<i class="fas fa-times me-1"></i> 取消
|
||||
</a>
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="fas fa-trash-alt me-1"></i> 确认删除
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
48
templates/confirm_delete_certificate.html
Normal file
48
templates/confirm_delete_certificate.html
Normal file
@ -0,0 +1,48 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}删除证书 - {{ cert.common_name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="card border-danger">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h4><i class="fas fa-exclamation-triangle me-2"></i> 确认删除证书</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">您确定要删除以下证书吗?</h5>
|
||||
<div class="alert alert-danger">
|
||||
<strong>警告:</strong>此操作不可逆!所有与此证书相关的文件将被永久删除。
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h6>证书信息:</h6>
|
||||
<ul>
|
||||
<li>通用名: {{ cert.common_name }}</li>
|
||||
<li>颁发CA: {{ cert.ca_name }}</li>
|
||||
<li>状态:
|
||||
{% if cert.status == 'active' %}
|
||||
<span class="badge bg-success">有效</span>
|
||||
{% elif cert.status == 'revoked' %}
|
||||
<span class="badge bg-danger">已吊销</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">已过期</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li>创建时间: {{ cert.created_at.strftime('%Y-%m-%d %H:%M') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url_for('delete_certificate', cert_id=cert.id) }}">
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{{ url_for('certificate_detail', cert_id=cert.id) }}" class="btn btn-secondary">
|
||||
<i class="fas fa-times me-1"></i> 取消
|
||||
</a>
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="fas fa-trash-alt me-1"></i> 确认删除
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Loading…
x
Reference in New Issue
Block a user