Files
ss-tools/backend/src/scripts/create_admin.py
busya 8d0bc6fb93 feat(translate,scheduler,trace): new-key-only mode, stale PENDING protection, trace_id propagation
Translations:
- FR-045: new-key-only execution mode — translate only rows with unseen keys
- Compare source row keys against TranslationRecord.source_data from last succeeded run
- Baseline expired (>90 days) fallback to full mode with baseline_expired event
- run_noop early return when zero new keys (skip LLM + SQL)

Scheduler reliability:
- Stale PENDING protection: runs older than 1h auto-marked FAILED, no longer block schedule
- load_schedules() reloads active translation schedules from DB on restart
- add_translation_job/remove_translation_job register/unregister with APScheduler
- execution_mode column on translation_schedules with additive DB migration

Automation view:
- GET /settings/automation/translation-schedules endpoint
- Translation schedules displayed on Automation page below validation policies

Trace propagation:
- seed_trace_id() in all background entry points:
  TaskManager._run_task/_flusher_loop, SchedulerService._trigger_backup,
  websocket_endpoint, IdMappingService, all standalone scripts

Migrations:
- dictionary_entries: origin_run_id, origin_row_key, origin_user_id
- translation_schedules: execution_mode

Tests:
- 3 new test modules (22 tests): core_scheduler, executor_filter, scheduler_execution+guard
- Fix pre-existing translate test isolation (conftest.py)
- Fix test_list_runs_filter_status parameter
2026-05-14 10:13:56 +03:00

95 lines
3.1 KiB
Python

# #region CreateAdminScript [C:3] [TYPE Module] [SEMANTICS admin, search, user, cli]
#
# @BRIEF CLI tool for creating the initial admin user.
# @LAYER: Scripts
# @RELATION USES -> [AuthSecurityModule]
# @RELATION USES -> [DatabaseModule]
# @RELATION USES -> [AuthModels]
#
# @INVARIANT: Admin user must have the "Admin" role.
import sys
import argparse
from pathlib import Path
# Add src to path
sys.path.append(str(Path(__file__).parent.parent.parent))
from src.core.database import AuthSessionLocal, init_db
from src.core.auth.security import get_password_hash
from src.models.auth import User, Role
from src.core.logger import logger, belief_scope
from src.core.cot_logger import seed_trace_id
# #region create_admin [TYPE Function]
# @BRIEF Creates an admin user and necessary roles/permissions.
# @PRE: username and password provided via CLI.
# @POST: Admin user exists in auth.db.
#
def create_admin(username, password, email=None):
seed_trace_id()
with belief_scope("create_admin"):
db = AuthSessionLocal()
try:
normalized_email = (
email.strip() if isinstance(email, str) and email.strip() else None
)
# 1. Ensure Admin role exists
admin_role = db.query(Role).filter(Role.name == "Admin").first()
if not admin_role:
logger.info("Creating Admin role...")
admin_role = Role(name="Admin", description="System Administrator")
db.add(admin_role)
db.commit()
db.refresh(admin_role)
# 2. Check if user already exists
existing_user = db.query(User).filter(User.username == username).first()
if existing_user:
logger.warning(f"User {username} already exists.")
return "exists"
# 3. Create Admin user
logger.info(f"Creating admin user: {username}")
new_user = User(
username=username,
email=normalized_email,
password_hash=get_password_hash(password),
auth_source="LOCAL",
is_active=True,
)
new_user.roles.append(admin_role)
db.add(new_user)
db.commit()
logger.info(f"Admin user {username} created successfully.")
return "created"
except Exception as e:
logger.error(f"Failed to create admin user: {e}")
db.rollback()
raise
finally:
db.close()
# #endregion create_admin
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Create initial admin user")
parser.add_argument("--username", required=True, help="Admin username")
parser.add_argument("--password", required=True, help="Admin password")
parser.add_argument("--email", required=False, help="Admin email")
args = parser.parse_args()
try:
# Ensure DB is initialized before creating admin
init_db()
create_admin(args.username, args.password, args.email)
sys.exit(0)
except Exception:
sys.exit(1)
# #endregion CreateAdminScript