```
feat(auth): 添加用户权限获取接口并完善JWT令牌角色信息 - 在JWT令牌中添加用户角色信息 - 新增get_my_permissions接口用于获取当前用户权限码列表 - 重构认证回调逻辑,增加错误日志记录 - 更新用户信息获取接口使用Authorization头验证 ```
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
"""rebuild users, permissions, role_permissions tables
|
||||
|
||||
Revision ID: a1b2c3d4e5f6
|
||||
Revises: 3e108afa9bba
|
||||
Create Date: 2026-04-05
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
revision: str = 'a1b2c3d4e5f6'
|
||||
down_revision: Union[str, None] = '3e108afa9bba'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
insp = sa.inspect(conn)
|
||||
existing = insp.get_table_names()
|
||||
|
||||
# 创建 permissions 表(如不存在)
|
||||
if 'permissions' not in existing:
|
||||
op.create_table(
|
||||
'permissions',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('name', sa.String(length=100), nullable=False),
|
||||
sa.Column('code', sa.String(length=50), nullable=False),
|
||||
sa.Column('module', sa.String(length=50), nullable=True),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code'),
|
||||
)
|
||||
|
||||
# 创建 users 表(如不存在)
|
||||
if 'users' not in existing:
|
||||
op.create_table(
|
||||
'users',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('casdoor_id', sa.String(length=100), nullable=False),
|
||||
sa.Column('username', sa.String(length=100), nullable=False),
|
||||
sa.Column('email', sa.String(length=255), nullable=True),
|
||||
sa.Column('role', sa.String(length=50), nullable=True, server_default='user'),
|
||||
sa.Column('assigned_area', sa.String(length=100), nullable=True),
|
||||
sa.Column('assigned_school', sa.String(length=200), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=True, server_default='true'),
|
||||
sa.Column('last_login', postgresql.TIMESTAMP(), nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('casdoor_id'),
|
||||
)
|
||||
op.create_index('ix_users_id', 'users', ['id'], unique=False)
|
||||
|
||||
# 创建 role_permissions 关联表(如不存在)
|
||||
if 'role_permissions' not in existing:
|
||||
op.create_table(
|
||||
'role_permissions',
|
||||
sa.Column('role', sa.String(length=50), nullable=False),
|
||||
sa.Column('permission_id', sa.BigInteger(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['permission_id'], ['permissions.id']),
|
||||
sa.PrimaryKeyConstraint('role', 'permission_id'),
|
||||
)
|
||||
|
||||
# 插入默认权限数据(跳过已存在的)
|
||||
permissions_table = sa.table(
|
||||
'permissions',
|
||||
sa.column('name', sa.String),
|
||||
sa.column('code', sa.String),
|
||||
sa.column('module', sa.String),
|
||||
sa.column('description', sa.Text),
|
||||
)
|
||||
op.bulk_insert(permissions_table, [
|
||||
{'name': '查看设备', 'code': 'device.view', 'module': 'device', 'description': '查看设备列表和详情'},
|
||||
{'name': '触发检查', 'code': 'device.check', 'module': 'device', 'description': '手动触发设备状态检查'},
|
||||
{'name': '导入设备', 'code': 'device.import', 'module': 'device', 'description': '通过Excel导入设备数据'},
|
||||
{'name': '编辑设备', 'code': 'device.edit', 'module': 'device', 'description': '编辑设备信息'},
|
||||
{'name': '删除设备', 'code': 'device.delete', 'module': 'device', 'description': '删除设备记录'},
|
||||
{'name': '查看OLT', 'code': 'olt.view', 'module': 'olt', 'description': '查看OLT设备列表'},
|
||||
{'name': '管理OLT', 'code': 'olt.manage', 'module': 'olt', 'description': '添加、编辑、删除OLT设备'},
|
||||
{'name': '查看用户', 'code': 'user.view', 'module': 'user', 'description': '查看用户列表'},
|
||||
{'name': '管理用户', 'code': 'user.manage', 'module': 'user', 'description': '修改用户角色和权限'},
|
||||
{'name': '系统管理', 'code': 'system.admin', 'module': 'system', 'description': '系统级管理操作'},
|
||||
])
|
||||
|
||||
# 插入默认角色权限
|
||||
op.execute("""
|
||||
INSERT INTO role_permissions (role, permission_id)
|
||||
SELECT 'area_admin', id FROM permissions WHERE code IN ('device.view', 'device.check', 'olt.view')
|
||||
""")
|
||||
op.execute("""
|
||||
INSERT INTO role_permissions (role, permission_id)
|
||||
SELECT 'school_admin', id FROM permissions WHERE code IN ('device.view')
|
||||
""")
|
||||
op.execute("""
|
||||
INSERT INTO role_permissions (role, permission_id)
|
||||
SELECT 'user', id FROM permissions WHERE code IN ('device.view')
|
||||
""")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_table('role_permissions')
|
||||
op.drop_index('ix_users_id', table_name='users')
|
||||
op.drop_table('users')
|
||||
op.drop_table('permissions')
|
||||
@@ -0,0 +1,28 @@
|
||||
"""add olt.port_manage, olt.discover, olt.loopback permissions
|
||||
|
||||
Revision ID: b2c3d4e5f6a7
|
||||
Revises: a1b2c3d4e5f6
|
||||
Create Date: 2026-04-05
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = 'b2c3d4e5f6a7'
|
||||
down_revision = 'a1b2c3d4e5f6'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("""
|
||||
INSERT INTO permissions (name, code, module, description)
|
||||
VALUES
|
||||
('端口管理', 'olt.port_manage', 'olt', '查看和切换OLT端口状态'),
|
||||
('扫描入库', 'olt.discover', 'olt', '扫描OLT并将新设备写入数据库'),
|
||||
('环路检测', 'olt.loopback', 'olt', '对OLT执行环路检测')
|
||||
ON CONFLICT (code) DO NOTHING
|
||||
""")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DELETE FROM permissions WHERE code IN ('olt.port_manage', 'olt.discover', 'olt.loopback')")
|
||||
@@ -0,0 +1,192 @@
|
||||
"""add inventory management tables and permissions
|
||||
|
||||
Revision ID: c3d4e5f6a7b8
|
||||
Revises: b2c3d4e5f6a7
|
||||
Create Date: 2026-04-05
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
revision: str = 'c3d4e5f6a7b8'
|
||||
down_revision: Union[str, None] = 'b2c3d4e5f6a7'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# 物料分类表
|
||||
op.create_table(
|
||||
'material_categories',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('name', sa.String(length=100), nullable=False),
|
||||
sa.Column('code', sa.String(length=50), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('code'),
|
||||
)
|
||||
|
||||
# 物料主数据表
|
||||
op.create_table(
|
||||
'materials',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('category_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('name', sa.String(length=200), nullable=False),
|
||||
sa.Column('model', sa.String(length=100), nullable=True),
|
||||
sa.Column('specification', sa.Text(), nullable=True),
|
||||
sa.Column('brand', sa.String(length=100), nullable=True),
|
||||
sa.Column('unit', sa.String(length=20), server_default='个', nullable=True),
|
||||
sa.Column('safe_quantity', sa.Integer(), server_default='0', nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.Column('updated_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.ForeignKeyConstraint(['category_id'], ['material_categories.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
)
|
||||
op.create_index('ix_materials_id', 'materials', ['id'], unique=False)
|
||||
|
||||
# 库存批次表
|
||||
op.create_table(
|
||||
'inventory_batches',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('material_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('batch_no', sa.String(length=50), nullable=False),
|
||||
sa.Column('quantity', sa.Integer(), nullable=False),
|
||||
sa.Column('available_quantity', sa.Integer(), nullable=False, server_default='0'),
|
||||
sa.Column('supplier', sa.String(length=200), nullable=True),
|
||||
sa.Column('purchase_date', sa.Date(), nullable=True),
|
||||
sa.Column('purchase_price', sa.Numeric(10, 2), nullable=True),
|
||||
sa.Column('expiry_date', sa.Date(), nullable=True),
|
||||
sa.Column('location', sa.String(length=100), nullable=True),
|
||||
sa.Column('status', sa.String(length=20), server_default='in_stock', nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.ForeignKeyConstraint(['material_id'], ['materials.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
)
|
||||
|
||||
# 序列号设备表
|
||||
op.create_table(
|
||||
'serial_devices',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('material_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('batch_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('serial_no', sa.String(length=100), nullable=False),
|
||||
sa.Column('mac_address', sa.String(length=17), nullable=True),
|
||||
sa.Column('asset_no', sa.String(length=50), nullable=True),
|
||||
sa.Column('status', sa.String(length=20), server_default='in_stock', nullable=True),
|
||||
sa.Column('current_location', sa.String(length=200), nullable=True),
|
||||
sa.Column('installed_info', postgresql.JSONB(), nullable=True),
|
||||
sa.Column('onu_device_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.Column('updated_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.ForeignKeyConstraint(['batch_id'], ['inventory_batches.id']),
|
||||
sa.ForeignKeyConstraint(['material_id'], ['materials.id']),
|
||||
sa.ForeignKeyConstraint(['onu_device_id'], ['onu_devices.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('serial_no'),
|
||||
)
|
||||
op.create_index('ix_serial_devices_mac_address', 'serial_devices', ['mac_address'], unique=False)
|
||||
op.create_index('ix_serial_devices_status', 'serial_devices', ['status'], unique=False)
|
||||
|
||||
# 出入库记录表
|
||||
op.create_table(
|
||||
'inventory_transactions',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('transaction_no', sa.String(length=50), nullable=False),
|
||||
sa.Column('transaction_type', sa.String(length=20), nullable=False),
|
||||
sa.Column('material_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('batch_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('serial_device_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('quantity', sa.Integer(), nullable=False),
|
||||
sa.Column('from_status', sa.String(length=20), nullable=True),
|
||||
sa.Column('to_status', sa.String(length=20), nullable=True),
|
||||
sa.Column('operator_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('project_name', sa.String(length=200), nullable=True),
|
||||
sa.Column('installation_info', postgresql.JSONB(), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.ForeignKeyConstraint(['batch_id'], ['inventory_batches.id']),
|
||||
sa.ForeignKeyConstraint(['material_id'], ['materials.id']),
|
||||
sa.ForeignKeyConstraint(['operator_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['serial_device_id'], ['serial_devices.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('transaction_no'),
|
||||
)
|
||||
|
||||
# 盘点记录表
|
||||
op.create_table(
|
||||
'inventory_checks',
|
||||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column('check_no', sa.String(length=50), nullable=False),
|
||||
sa.Column('check_date', sa.Date(), nullable=False),
|
||||
sa.Column('checker_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('material_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('batch_id', sa.BigInteger(), nullable=True),
|
||||
sa.Column('book_quantity', sa.Integer(), nullable=True),
|
||||
sa.Column('actual_quantity', sa.Integer(), nullable=True),
|
||||
sa.Column('difference', sa.Integer(), nullable=True),
|
||||
sa.Column('reason', sa.Text(), nullable=True),
|
||||
sa.Column('adjusted', sa.Boolean(), server_default='false', nullable=True),
|
||||
sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('now()'), nullable=True),
|
||||
sa.ForeignKeyConstraint(['batch_id'], ['inventory_batches.id']),
|
||||
sa.ForeignKeyConstraint(['checker_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['material_id'], ['materials.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('check_no'),
|
||||
)
|
||||
|
||||
# 新增库存管理权限
|
||||
permissions_table = sa.table(
|
||||
'permissions',
|
||||
sa.column('name', sa.String),
|
||||
sa.column('code', sa.String),
|
||||
sa.column('module', sa.String),
|
||||
sa.column('description', sa.Text),
|
||||
)
|
||||
op.bulk_insert(permissions_table, [
|
||||
{'name': '查看库存', 'code': 'inventory.view', 'module': 'inventory', 'description': '查看库存列表和统计'},
|
||||
{'name': '管理物料', 'code': 'inventory.manage', 'module': 'inventory', 'description': '创建、编辑、删除物料'},
|
||||
{'name': '出入库操作', 'code': 'inventory.transaction', 'module': 'inventory', 'description': '执行采购入库、领用出库、退库操作'},
|
||||
{'name': '库存盘点', 'code': 'inventory.check', 'module': 'inventory', 'description': '创建盘点单并执行库存调整'},
|
||||
{'name': '库存报表', 'code': 'inventory.report', 'module': 'inventory', 'description': '查看库存统计报表'},
|
||||
])
|
||||
|
||||
# 默认给 area_admin 查看权限
|
||||
op.execute("""
|
||||
INSERT INTO role_permissions (role, permission_id)
|
||||
SELECT 'area_admin', id FROM permissions WHERE code = 'inventory.view'
|
||||
""")
|
||||
|
||||
# 插入默认物料分类
|
||||
op.execute("""
|
||||
INSERT INTO material_categories (name, code, description) VALUES
|
||||
('ONU设备', 'ONU', '光网络单元设备'),
|
||||
('OLT设备', 'OLT', '光线路终端设备'),
|
||||
('交换机', 'SWITCH', '网络交换机'),
|
||||
('防火墙', 'FIREWALL', '网络防火墙设备'),
|
||||
('上网行为管理', 'BEHAVIOR', '上网行为管理设备'),
|
||||
('光模块及配件', 'ACCESSORY', '光模块、跳线等配件')
|
||||
""")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_table('inventory_checks')
|
||||
op.drop_table('inventory_transactions')
|
||||
op.drop_index('ix_serial_devices_status', table_name='serial_devices')
|
||||
op.drop_index('ix_serial_devices_mac_address', table_name='serial_devices')
|
||||
op.drop_table('serial_devices')
|
||||
op.drop_table('inventory_batches')
|
||||
op.drop_index('ix_materials_id', table_name='materials')
|
||||
op.drop_table('materials')
|
||||
op.drop_table('material_categories')
|
||||
op.execute("""
|
||||
DELETE FROM role_permissions WHERE permission_id IN (
|
||||
SELECT id FROM permissions WHERE module = 'inventory'
|
||||
)
|
||||
""")
|
||||
op.execute("DELETE FROM permissions WHERE module = 'inventory'")
|
||||
@@ -0,0 +1,26 @@
|
||||
"""add region to olt_devices
|
||||
|
||||
Revision ID: d4e5f6a7b8c9
|
||||
Revises: c3d4e5f6a7b8
|
||||
Create Date: 2026-04-05
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = 'd4e5f6a7b8c9'
|
||||
down_revision = 'c3d4e5f6a7b8'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('olt_devices', sa.Column('region', sa.String(100), nullable=True))
|
||||
op.create_index('ix_olt_devices_region', 'olt_devices', ['region'])
|
||||
# 默认将现有 OLT 设置为城区
|
||||
op.execute("UPDATE olt_devices SET region = '城区' WHERE region IS NULL")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_index('ix_olt_devices_region', 'olt_devices')
|
||||
op.drop_column('olt_devices', 'region')
|
||||
@@ -0,0 +1,32 @@
|
||||
"""add device_daily_snapshots table
|
||||
|
||||
Revision ID: e5f6a7b8c9d0
|
||||
Revises: d4e5f6a7b8c9
|
||||
Create Date: 2026-04-05
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = 'e5f6a7b8c9d0'
|
||||
down_revision = 'd4e5f6a7b8c9'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'device_daily_snapshots',
|
||||
sa.Column('id', sa.BigInteger(), primary_key=True, index=True),
|
||||
sa.Column('snapshot_date', sa.String(10), nullable=False),
|
||||
sa.Column('total', sa.Integer(), nullable=False, server_default='0'),
|
||||
sa.Column('online', sa.Integer(), nullable=False, server_default='0'),
|
||||
sa.Column('offline', sa.Integer(), nullable=False, server_default='0'),
|
||||
sa.Column('created_at', sa.TIMESTAMP(), server_default=sa.text('now()')),
|
||||
)
|
||||
op.create_index('ix_device_daily_snapshots_snapshot_date', 'device_daily_snapshots', ['snapshot_date'])
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_index('ix_device_daily_snapshots_snapshot_date', 'device_daily_snapshots')
|
||||
op.drop_table('device_daily_snapshots')
|
||||
@@ -0,0 +1,33 @@
|
||||
"""add system_settings table
|
||||
|
||||
Revision ID: f6a7b8c9d0e1
|
||||
Revises: e5f6a7b8c9d0
|
||||
Create Date: 2026-04-05
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = 'f6a7b8c9d0e1'
|
||||
down_revision = 'e5f6a7b8c9d0'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'system_settings',
|
||||
sa.Column('key', sa.String(100), primary_key=True),
|
||||
sa.Column('value', sa.Text(), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('updated_at', sa.TIMESTAMP(), server_default=sa.text('now()')),
|
||||
)
|
||||
# 插入默认值
|
||||
op.execute("""
|
||||
INSERT INTO system_settings (key, value, description)
|
||||
VALUES ('check_interval_seconds', '1800', '定时检查间隔(秒),最小 300(5分钟)')
|
||||
""")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table('system_settings')
|
||||
@@ -0,0 +1,55 @@
|
||||
"""add audit_logs table
|
||||
|
||||
Revision ID: g7h8i9j0k1l2
|
||||
Revises: f6a7b8c9d0e1
|
||||
Create Date: 2026-04-05
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
revision = 'g7h8i9j0k1l2'
|
||||
down_revision = 'f6a7b8c9d0e1'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'audit_logs',
|
||||
sa.Column('id', sa.Integer(), primary_key=True),
|
||||
sa.Column('user_id', sa.String(100), nullable=False),
|
||||
sa.Column('username', sa.String(100), nullable=False),
|
||||
sa.Column('user_role', sa.String(50)),
|
||||
sa.Column('action_time', sa.TIMESTAMP(), nullable=False, server_default=sa.text('now()')),
|
||||
sa.Column('action_type', sa.String(50), nullable=False),
|
||||
sa.Column('action_subtype', sa.String(50)),
|
||||
sa.Column('ip_address', sa.String(45)),
|
||||
sa.Column('user_agent', sa.Text()),
|
||||
sa.Column('request_method', sa.String(10)),
|
||||
sa.Column('request_path', sa.String(500)),
|
||||
sa.Column('status', sa.String(20), nullable=False),
|
||||
sa.Column('status_code', sa.Integer()),
|
||||
sa.Column('resource_type', sa.String(50)),
|
||||
sa.Column('resource_id', sa.String(100)),
|
||||
sa.Column('resource_name', sa.String(200)),
|
||||
sa.Column('description', sa.Text(), nullable=False),
|
||||
sa.Column('request_params', JSONB()),
|
||||
sa.Column('response_data', JSONB()),
|
||||
sa.Column('error_message', sa.Text()),
|
||||
sa.Column('created_at', sa.TIMESTAMP(), nullable=False, server_default=sa.text('now()')),
|
||||
)
|
||||
op.create_index('idx_audit_logs_action_time', 'audit_logs', ['action_time'])
|
||||
op.create_index('idx_audit_logs_user_id', 'audit_logs', ['user_id'])
|
||||
op.create_index('idx_audit_logs_action_type', 'audit_logs', ['action_type'])
|
||||
op.create_index('idx_audit_logs_resource_type', 'audit_logs', ['resource_type'])
|
||||
op.create_index('idx_audit_logs_status', 'audit_logs', ['status'])
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_index('idx_audit_logs_status', 'audit_logs')
|
||||
op.drop_index('idx_audit_logs_resource_type', 'audit_logs')
|
||||
op.drop_index('idx_audit_logs_action_type', 'audit_logs')
|
||||
op.drop_index('idx_audit_logs_user_id', 'audit_logs')
|
||||
op.drop_index('idx_audit_logs_action_time', 'audit_logs')
|
||||
op.drop_table('audit_logs')
|
||||
@@ -0,0 +1,38 @@
|
||||
"""add device_replacements table
|
||||
|
||||
Revision ID: h8i9j0k1l2m3
|
||||
Revises: g7h8i9j0k1l2
|
||||
Create Date: 2026-04-05
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = 'h8i9j0k1l2m3'
|
||||
down_revision = 'g7h8i9j0k1l2'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'device_replacements',
|
||||
sa.Column('id', sa.BigInteger(), primary_key=True),
|
||||
sa.Column('onu_device_id', sa.BigInteger(), sa.ForeignKey('onu_devices.id'), nullable=False),
|
||||
sa.Column('old_mac', sa.String(17), nullable=False),
|
||||
sa.Column('new_mac', sa.String(17), nullable=False),
|
||||
sa.Column('reason', sa.Text()),
|
||||
sa.Column('operator_id', sa.String(100)),
|
||||
sa.Column('operator_name', sa.String(100)),
|
||||
sa.Column('replaced_at', sa.TIMESTAMP(), nullable=False, server_default=sa.text('now()')),
|
||||
sa.Column('created_at', sa.TIMESTAMP(), nullable=False, server_default=sa.text('now()')),
|
||||
)
|
||||
op.create_index('idx_device_replacements_onu_device_id', 'device_replacements', ['onu_device_id'])
|
||||
op.create_index('idx_device_replacements_old_mac', 'device_replacements', ['old_mac'])
|
||||
op.create_index('idx_device_replacements_new_mac', 'device_replacements', ['new_mac'])
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_index('idx_device_replacements_new_mac', 'device_replacements')
|
||||
op.drop_index('idx_device_replacements_old_mac', 'device_replacements')
|
||||
op.drop_index('idx_device_replacements_onu_device_id', 'device_replacements')
|
||||
op.drop_table('device_replacements')
|
||||
Reference in New Issue
Block a user