146 lines
4.7 KiB
Python
146 lines
4.7 KiB
Python
|
|
"""添加安全约束
|
|||
|
|
|
|||
|
|
Revision ID: 20251212_add_security_constraints
|
|||
|
|
Revises:
|
|||
|
|
Create Date: 2025-12-12 00:00:00.000000
|
|||
|
|
|
|||
|
|
"""
|
|||
|
|
from alembic import op
|
|||
|
|
import sqlalchemy as sa
|
|||
|
|
from sqlalchemy.dialects import postgresql
|
|||
|
|
|
|||
|
|
# revision identifiers
|
|||
|
|
revision = '20251212_add_security_constraints'
|
|||
|
|
down_revision = None
|
|||
|
|
branch_labels = None
|
|||
|
|
depends_on = None
|
|||
|
|
|
|||
|
|
|
|||
|
|
def upgrade():
|
|||
|
|
"""
|
|||
|
|
添加数据库层面的安全约束
|
|||
|
|
"""
|
|||
|
|
# 为License表添加约束
|
|||
|
|
# 1. 解绑次数约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_license_unbind_count',
|
|||
|
|
'license',
|
|||
|
|
'unbind_count >= 0 AND unbind_count <= 10' # 解绑次数不能超过10次
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 2. 有效天数约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_license_valid_days',
|
|||
|
|
'license',
|
|||
|
|
'valid_days > 0 OR valid_days = -1' # 有效天数必须为正数或-1(永久有效)
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 3. 状态值约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_license_status',
|
|||
|
|
'license',
|
|||
|
|
'status IN (0, 1, 2, 3)' # 0=未激活,1=已激活,2=已过期,3=已禁用
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 4. 绑定次数约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_license_max_bind_times',
|
|||
|
|
'license',
|
|||
|
|
'max_bind_times > 0 AND max_bind_times <= 100' # 最大绑定次数限制
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 为Product表添加约束
|
|||
|
|
# 1. 价格约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_product_price',
|
|||
|
|
'product',
|
|||
|
|
'price >= 0' # 价格不能为负数
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 2. 状态值约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_product_status',
|
|||
|
|
'product',
|
|||
|
|
'status IN (0, 1)' # 0=禁用,1=启用
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 为Order表添加约束
|
|||
|
|
# 1. 金额约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_order_amount',
|
|||
|
|
'order',
|
|||
|
|
'amount > 0' # 订单金额必须为正数
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 2. 状态值约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_order_status',
|
|||
|
|
'order',
|
|||
|
|
'status IN (0, 1, 2, 3, 4)' # 0=待支付,1=已支付,2=已取消,3=已退款,4=已完成
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 为Ticket表添加约束
|
|||
|
|
# 1. 优先级约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_ticket_priority',
|
|||
|
|
'ticket',
|
|||
|
|
'priority IN (1, 2, 3, 4, 5)' # 1=低,2=中,3=高,4=紧急,5=非常重要
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 2. 状态值约束
|
|||
|
|
op.create_check_constraint(
|
|||
|
|
'chk_ticket_status',
|
|||
|
|
'ticket',
|
|||
|
|
'status IN (0, 1, 2, 3)' # 0=待处理,1=处理中,2=已解决,3=已关闭
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 添加索引优化查询性能
|
|||
|
|
# 1. License表的索引
|
|||
|
|
op.create_index('idx_license_product_status', 'license', ['product_id', 'status'])
|
|||
|
|
op.create_index('idx_license_type_status', 'license', ['type', 'status'])
|
|||
|
|
op.create_index('idx_license_key', 'license', ['license_key'], unique=True)
|
|||
|
|
|
|||
|
|
# 2. Product表的索引
|
|||
|
|
op.create_index('idx_product_status_type', 'product', ['status', 'product_type'])
|
|||
|
|
|
|||
|
|
# 3. Order表的索引
|
|||
|
|
op.create_index('idx_order_user_phone', 'order', ['user_phone'])
|
|||
|
|
op.create_index('idx_order_status_time', 'order', ['status', 'create_time'])
|
|||
|
|
|
|||
|
|
# 4. Ticket表的索引
|
|||
|
|
op.create_index('idx_ticket_user_phone', 'ticket', ['user_phone'])
|
|||
|
|
op.create_index('idx_ticket_status_priority', 'ticket', ['status', 'priority'])
|
|||
|
|
|
|||
|
|
# 5. Device表的索引
|
|||
|
|
op.create_index('idx_device_machine_code', 'device', ['machine_code'])
|
|||
|
|
op.create_index('idx_device_license', 'device', ['license_id'])
|
|||
|
|
|
|||
|
|
|
|||
|
|
def downgrade():
|
|||
|
|
"""
|
|||
|
|
删除安全约束
|
|||
|
|
"""
|
|||
|
|
# 删除索引
|
|||
|
|
op.drop_index('idx_device_license', 'device')
|
|||
|
|
op.drop_index('idx_device_machine_code', 'device')
|
|||
|
|
op.drop_index('idx_ticket_status_priority', 'ticket')
|
|||
|
|
op.drop_index('idx_ticket_user_phone', 'ticket')
|
|||
|
|
op.drop_index('idx_order_status_time', 'order')
|
|||
|
|
op.drop_index('idx_order_user_phone', 'order')
|
|||
|
|
op.drop_index('idx_product_status_type', 'product')
|
|||
|
|
op.drop_index('idx_license_key', 'license')
|
|||
|
|
op.drop_index('idx_license_type_status', 'license')
|
|||
|
|
op.drop_index('idx_license_product_status', 'license')
|
|||
|
|
|
|||
|
|
# 删除约束
|
|||
|
|
op.drop_constraint('chk_ticket_status', 'ticket', type_='check')
|
|||
|
|
op.drop_constraint('chk_ticket_priority', 'ticket', type_='check')
|
|||
|
|
op.drop_constraint('chk_order_status', 'order', type_='check')
|
|||
|
|
op.drop_constraint('chk_order_amount', 'order', type_='check')
|
|||
|
|
op.drop_constraint('chk_product_status', 'product', type_='check')
|
|||
|
|
op.drop_constraint('chk_product_price', 'product', type_='check')
|
|||
|
|
op.drop_constraint('chk_license_max_bind_times', 'license', type_='check')
|
|||
|
|
op.drop_constraint('chk_license_status', 'license', type_='check')
|
|||
|
|
op.drop_constraint('chk_license_valid_days', 'license', type_='check')
|
|||
|
|
op.drop_constraint('chk_license_unbind_count', 'license', type_='check')
|