backfill-company-owner.js 1.92 KB
#!/usr/bin/env node
/**
 * backfill-company-owner.js —— 存量公司补 ownerId
 *
 * 依据: docs/todo/system-design/38-auth-multi-tenant-isolation.md §3.5 / Phase 2
 *
 * `data/companies/{id}/company.json` 在加公司归属隔离之前建的公司都没有 ownerId 字段——
 * 统一划给种子账号 admin(用户已明确拍板,见文档 §一)。
 *
 * 幂等: 已经有 ownerId 的行跳过,可重复执行。
 *
 * 用法:
 *   node scripts/backfill-company-owner.js
 */

const fs = require('fs');
const path = require('path');

const DATA_DIR = path.resolve(__dirname, '../data/companies');
const SEED_EMAIL = 'admin';

function main() {
  const userDb = require('../server/services/user-db');
  const admin = userDb.findByEmail(SEED_EMAIL);
  if (!admin) {
    console.error(`[backfill-company-owner] 找不到种子账号 "${SEED_EMAIL}",先跑 npm run seed:admin`);
    process.exit(1);
  }

  if (!fs.existsSync(DATA_DIR)) {
    console.log('[backfill-company-owner] data/companies/ 不存在,无需处理');
    return;
  }

  const dirs = fs.readdirSync(DATA_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
  let migrated = 0;
  let skipped = 0;

  for (const d of dirs) {
    const fp = path.join(DATA_DIR, d.name, 'company.json');
    if (!fs.existsSync(fp)) continue;

    const company = JSON.parse(fs.readFileSync(fp, 'utf-8'));
    if (company.ownerId != null) {
      skipped += 1;
      continue;
    }

    company.ownerId = admin.id;
    company.updatedAt = new Date().toISOString();
    // 跟 company-service.js 的 _saveCompany 保持同一种写法(无结尾换行),别引入格式差异。
    fs.writeFileSync(fp, JSON.stringify(company, null, 2), 'utf-8');
    console.log(`[backfill-company-owner] ${d.name} → ownerId=${admin.id}`);
    migrated += 1;
  }

  console.log(`[backfill-company-owner] 完成:迁移 ${migrated} 家,跳过(已有 ownerId)${skipped} 家`);
}

main();