329 lines
9.2 KiB
JavaScript
329 lines
9.2 KiB
JavaScript
#!/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
|
||
};
|