添加查看调度运行结果

This commit is contained in:
Winnie
2026-08-05 16:34:35 +08:00
parent c263ae6a5f
commit 30cde4a56c
8 changed files with 1140 additions and 36 deletions
@@ -0,0 +1,27 @@
"""reconcile the legacy remote database revision
Revision ID: d4e5f6a7b8c9
Revises: a2b3c4d5e6f7
Create Date: 2026-08-05 15:30:00
The shared development database was stamped with this revision by an older
migration history. The corresponding file was lost while branches were
merged. Keeping the marker in the active chain lets Alembic safely continue
without rewriting the existing database or replaying the baseline migration.
"""
from collections.abc import Sequence
revision: str = "d4e5f6a7b8c9"
down_revision: str | Sequence[str] | None = "a2b3c4d5e6f7"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
"""Preserve the already-applied legacy revision marker."""
def downgrade() -> None:
"""The compatibility marker has no schema operation to reverse."""
@@ -0,0 +1,158 @@
"""ensure the self-hosted demo login remains available
Revision ID: e5f6a7b8c9d0
Revises: d4e5f6a7b8c9
Create Date: 2026-08-05 15:31:00
"""
from collections.abc import Sequence
import os
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
from common.auth.passwords import hash_password
revision: str = "e5f6a7b8c9d0"
down_revision: str | Sequence[str] | None = "d4e5f6a7b8c9"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
DISABLED_PASSWORD = "demo-login-disabled"
SEEDED_USERS = (
(
"0000000000RF6FG1SDBXG59S13",
"admin-zhang",
"张三",
"0000000000000000000000000A",
),
(
"0000000000H2QYCGPCWQM1JSGS",
"admin-li",
"李四",
"0000000000000000000000000A",
),
(
"0000000000RWG40ESZPGJT629J",
"dev-wang",
"王五",
"0000000000000000000000000B",
),
(
"00000000004CQV7WASJA6N6FW4",
"dev-zhao",
"赵六",
"0000000000000000000000000B",
),
)
def _create_users_table() -> None:
op.create_table(
"users",
sa.Column("user_id", mysql.CHAR(length=26), nullable=False),
sa.Column("username", sa.String(length=64), nullable=False),
sa.Column("display_name", sa.String(length=100), nullable=False),
sa.Column("password_hash", sa.String(length=255), nullable=False),
sa.Column(
"status",
sa.String(length=16),
server_default=sa.text("'active'"),
nullable=False,
comment="active/disabled/locked",
),
sa.Column(
"created_at",
mysql.DATETIME(fsp=3),
server_default=sa.text("CURRENT_TIMESTAMP(3)"),
nullable=False,
),
sa.Column(
"updated_at",
mysql.DATETIME(fsp=3),
server_default=sa.text(
"CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
),
nullable=False,
),
sa.Column("email", sa.String(length=255), nullable=True),
sa.Column("platform_role_id", mysql.CHAR(length=26), nullable=True),
sa.Column("avatar_uri", sa.String(length=1000), nullable=True),
sa.Column("last_login_at", mysql.DATETIME(fsp=3), nullable=True),
sa.Column(
"is_deleted",
mysql.TINYINT(display_width=1),
server_default=sa.text("0"),
nullable=False,
),
sa.Column("deleted_at", mysql.DATETIME(fsp=3), nullable=True),
sa.PrimaryKeyConstraint("user_id"),
comment="平台用户",
)
op.create_index("fk_users_platform_role", "users", ["platform_role_id"])
op.create_index("idx_users_status", "users", ["status"])
op.create_index("uk_users_email", "users", ["email"], unique=True)
op.create_index("uk_users_username", "users", ["username"], unique=True)
def upgrade() -> None:
connection = op.get_bind()
if not sa.inspect(connection).has_table("users"):
_create_users_table()
users = sa.table(
"users",
sa.column("user_id", sa.String),
sa.column("username", sa.String),
sa.column("display_name", sa.String),
sa.column("password_hash", sa.String),
sa.column("status", sa.String),
sa.column("email", sa.String),
sa.column("platform_role_id", sa.String),
)
existing = {
row.username: row.password_hash
for row in connection.execute(
sa.select(users.c.username, users.c.password_hash).where(
users.c.username.in_([user[1] for user in SEEDED_USERS])
)
)
}
password_hash = hash_password(
os.environ.get("INITIAL_ADMIN_PASSWORD", "admin12345")
)
for user_id, username, display_name, role_id in SEEDED_USERS:
if username not in existing:
connection.execute(
users.insert().values(
user_id=user_id,
username=username,
display_name=display_name,
password_hash=password_hash,
status="active",
email=f"{username}@model-platform.local",
platform_role_id=role_id,
)
)
continue
if existing[username] in {None, "", DISABLED_PASSWORD}:
connection.execute(
users.update()
.where(users.c.username == username)
.values(password_hash=password_hash)
)
connection.execute(
users.update()
.where(users.c.username == "admin-zhang")
.values(status="active")
)
def downgrade() -> None:
"""Do not remove or disable accounts that may contain user data."""