#!/usr/bin/env node /** * Supabase Auth 用户批量创建脚本 * 使用 Supabase Admin API 创建测试用户 * * 使用方法: * 1. npm install @supabase/supabase-js * 2. 设置环境变量 SUPABASE_URL 和 SUPABASE_SERVICE_ROLE_KEY * 3. 运行: node create_supabase_auth_users.js */ const { createClient } = require('@supabase/supabase-js'); // 配置信息 const config = { // 从环境变量获取,或在此处直接配置(仅限开发环境) supabaseUrl: process.env.SUPABASE_URL || '', supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY || '', // 测试用户配置 testUsers: [ { email: 'admin@mall.com', password: 'Test123456!', user_metadata: { name: '系统管理员', role: 'admin', nickname: '系统管理员' } }, { email: 'merchant1@mall.com', password: 'Test123456!', user_metadata: { name: '数码专营店', role: 'merchant', nickname: '数码专营店' } }, { email: 'merchant2@mall.com', password: 'Test123456!', user_metadata: { name: '时尚服饰店', role: 'merchant', nickname: '时尚服饰店' } }, { email: 'customer1@mall.com', password: 'Test123456!', user_metadata: { name: '张小明', role: 'customer', nickname: '张小明' } }, { email: 'customer2@mall.com', password: 'Test123456!', user_metadata: { name: '李小红', role: 'customer', nickname: '李小红' } }, { email: 'customer3@mall.com', password: 'Test123456!', user_metadata: { name: '王小华', role: 'customer', nickname: '王小华' } }, { email: 'driver1@mall.com', password: 'Test123456!', user_metadata: { name: '快递小哥1', role: 'delivery', nickname: '快递小哥1' } }, { email: 'driver2@mall.com', password: 'Test123456!', user_metadata: { name: '快递小哥2', role: 'delivery', nickname: '快递小哥2' } } ] }; // 日志函数 const log = { info: (msg) => console.log(`ℹ️ ${msg}`), success: (msg) => console.log(`✅ ${msg}`), warning: (msg) => console.log(`⚠️ ${msg}`), error: (msg) => console.log(`❌ ${msg}`), separator: () => console.log('===============================================') }; // 检查配置 function checkConfig() { log.separator(); log.info('检查配置信息...'); if (!config.supabaseUrl) { log.error('缺少 SUPABASE_URL 环境变量'); log.info('请设置: export SUPABASE_URL="https://your-project.supabase.co"'); return false; } if (!config.supabaseServiceRoleKey) { log.error('缺少 SUPABASE_SERVICE_ROLE_KEY 环境变量'); log.info('请设置: export SUPABASE_SERVICE_ROLE_KEY="your-service-role-key"'); log.warning('Service Role Key 可在 Supabase Dashboard -> Settings -> API 中找到'); return false; } log.success('配置检查通过'); log.info(`Supabase URL: ${config.supabaseUrl}`); log.info(`Service Role Key: ${config.supabaseServiceRoleKey.substring(0, 20)}...`); return true; } // 创建 Supabase 客户端 function createSupabaseClient() { try { return createClient(config.supabaseUrl, config.supabaseServiceRoleKey, { auth: { autoRefreshToken: false, persistSession: false } }); } catch (error) { log.error(`创建 Supabase 客户端失败: ${error.message}`); return null; } } // 检查现有用户 async function checkExistingUsers(supabase) { log.separator(); log.info('检查现有用户...'); try { const { data: { users }, error } = await supabase.auth.admin.listUsers(); if (error) { log.error(`获取用户列表失败: ${error.message}`); return []; } const existingEmails = users .filter(user => user.email && user.email.includes('@mall.com')) .map(user => user.email); log.info(`找到 ${existingEmails.length} 个现有测试用户`); existingEmails.forEach(email => log.success(`已存在: ${email}`)); return existingEmails; } catch (error) { log.error(`检查用户时出错: ${error.message}`); return []; } } // 创建单个用户 async function createUser(supabase, userConfig) { try { const { data, error } = await supabase.auth.admin.createUser({ email: userConfig.email, password: userConfig.password, email_confirm: true, // 自动确认邮箱 user_metadata: userConfig.user_metadata }); if (error) { // 检查是否是重复邮箱错误 if (error.message.includes('already registered') || error.message.includes('already exists')) { log.warning(`用户已存在: ${userConfig.email}`); return { success: true, existed: true }; } else { log.error(`创建用户失败 ${userConfig.email}: ${error.message}`); return { success: false, error: error.message }; } } log.success(`创建用户成功: ${userConfig.email} (ID: ${data.user.id})`); return { success: true, existed: false, user: data.user }; } catch (error) { log.error(`创建用户异常 ${userConfig.email}: ${error.message}`); return { success: false, error: error.message }; } } // 批量创建用户 async function createAllUsers(supabase) { log.separator(); log.info('开始批量创建用户...'); const results = { created: 0, existed: 0, failed: 0, details: [] }; for (const userConfig of config.testUsers) { log.info(`正在处理: ${userConfig.email} (${userConfig.user_metadata.name})`); const result = await createUser(supabase, userConfig); if (result.success) { if (result.existed) { results.existed++; } else { results.created++; } } else { results.failed++; } results.details.push({ email: userConfig.email, result: result }); // 短暂延迟,避免API限流 await new Promise(resolve => setTimeout(resolve, 100)); } return results; } // 显示最终结果 function showResults(results) { log.separator(); log.info('用户创建结果汇总'); log.separator(); log.info(`总计用户: ${config.testUsers.length}`); log.success(`新创建: ${results.created}`); log.warning(`已存在: ${results.existed}`); log.error(`失败: ${results.failed}`); if (results.failed > 0) { log.separator(); log.error('失败详情:'); results.details .filter(detail => !detail.result.success) .forEach(detail => { log.error(`${detail.email}: ${detail.result.error}`); }); } if (results.created > 0 || results.existed > 0) { log.separator(); log.success('可以继续执行后续步骤:'); log.info('1. 执行: psql -f create_supabase_auth_users.sql'); log.info('2. 执行: psql -f mock_data_insert.sql'); log.info('3. 验证用户数据是否正确关联'); } log.separator(); } // 主函数 async function main() { console.log('🚀 Supabase Auth 用户批量创建工具'); // 检查配置 if (!checkConfig()) { process.exit(1); } // 创建客户端 const supabase = createSupabaseClient(); if (!supabase) { process.exit(1); } try { // 检查现有用户 const existingUsers = await checkExistingUsers(supabase); // 批量创建用户 const results = await createAllUsers(supabase); // 显示结果 showResults(results); process.exit(results.failed > 0 ? 1 : 0); } catch (error) { log.error(`执行过程中出现异常: ${error.message}`); log.error(error.stack); process.exit(1); } } // 检查依赖 try { require('@supabase/supabase-js'); } catch (error) { log.error('缺少依赖包 @supabase/supabase-js'); log.info('请安装: npm install @supabase/supabase-js'); process.exit(1); } // 运行主函数 if (require.main === module) { main(); } module.exports = { config, createSupabaseClient, createUser, createAllUsers };